//# PlotTool.cc: Tool class definitions (higher-level event handlers). //# Copyright (C) 2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library 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 Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: $ #include <graphics/GenericPlotter/PlotTool.h> #include <graphics/GenericPlotter/PlotFactory.h> /////!!!!! + + ++ + + + + + + + + + #include <qwt/qwt_plot_picker.h> -- needed for draw rubber band box in different color #include <iomanip> using namespace std; using namespace casacore; namespace casa { ////////////////////////// // PLOTTOOL DEFINITIONS // ////////////////////////// PlotTool::PlotTool(PlotCoordinate::System sys) : m_canvas(NULL),m_factory(NULL), m_active(false), m_blocking(true), m_xAxis(X_BOTTOM), m_yAxis(Y_LEFT), m_coordSystem(sys), m_lastEventHandled(false) { } PlotTool::PlotTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System sys) : m_canvas(NULL), m_factory(NULL), m_active(false), m_blocking(true), m_xAxis(xAxis), m_yAxis(yAxis), m_coordSystem(sys), m_lastEventHandled(false) { } PlotTool::~PlotTool() { if(m_factory != NULL) delete m_factory; } bool PlotTool::isActive() const { return m_active; } void PlotTool::setActive(bool isActive) { m_active = isActive; } bool PlotTool::isBlocking() const { return m_blocking; } void PlotTool::setBlocking(bool blocking) { m_blocking = blocking; } PlotAxis PlotTool::getXAxis() const { return m_xAxis; } PlotAxis PlotTool::getYAxis() const { return m_yAxis; } PlotCoordinate::System PlotTool::getCoordinateSystem() const { return m_coordSystem; } bool PlotTool::lastEventWasHandled() const { return m_lastEventHandled; } PlotCanvas* PlotTool::canvas() const { return m_canvas; } PlotFactory* PlotTool::factory() const { return m_factory; } bool PlotTool::isAttached() const { return m_canvas != NULL; } void PlotTool::attach(PlotCanvas* canvas) { if(m_canvas != NULL) detach(); m_canvas = canvas; if(m_canvas != NULL) { // only generate a new factory if needed if(m_factory == NULL) m_factory = m_canvas->implementationFactory(); else if(m_factory->implementation() != m_canvas->implementation()){ delete m_factory; m_factory = m_canvas->implementationFactory(); } } } void PlotTool::detach() { m_canvas = NULL; } //////////////////////////////// // PLOTSELECTTOOL DEFINITIONS // //////////////////////////////// PlotSelectTool::PlotSelectTool(PlotCoordinate::System system) : PlotMouseTool(system), m_subtraction_mode(false), m_drawRects(false) { } PlotSelectTool::PlotSelectTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System system) : PlotMouseTool(xAxis, yAxis, system), m_subtraction_mode(false), m_drawRects(false) { } PlotSelectTool::~PlotSelectTool() { } void PlotSelectTool::addNotifier(PlotSelectToolNotifier* notifier) { if(notifier == NULL) return; for(unsigned int i = 0; i < m_notifiers.size(); i++) if(m_notifiers[i] == notifier) return; m_notifiers.push_back(notifier); } void PlotSelectTool::setSelectLine(PlotLinePtr line) { if(line != m_selLine) { m_selLine = line; if(m_canvas != NULL) { if(!line.null() && !m_subtraction_mode /*DSW:not sure if this test is needed. fix also next method.*/) m_canvas->setSelectLine(line); else m_canvas->setSelectLineShown(false); } } } void PlotSelectTool::setSubtractLine(PlotLinePtr line) { if(line != m_subLine) { m_subLine = line; if(m_canvas != NULL) { if(!line.null() && m_subtraction_mode) m_canvas->setSelectLine(line); else m_canvas->setSelectLineShown(false); } } } void PlotSelectTool::setSelectLine(bool on) { if(m_canvas != NULL) m_canvas->setSelectLineShown(on); } void PlotSelectTool::setDrawRects(bool on) { if(on != m_drawRects) { if(m_canvas != NULL && m_rects.size() > 0) { for(unsigned int i = 0; i < m_rects.size(); i++) { if(on) m_canvas->drawShape(m_rects[i]); else m_canvas->removeShape(m_rects[i]); } } m_drawRects = on; } } void PlotSelectTool::setRectLine(PlotLinePtr line) { if(line != m_rectLine) { m_rectLine = line; for(unsigned int i = 0; i < m_rects.size(); i++) m_rects[i]->setLine(line); } } void PlotSelectTool::setRectFill(PlotAreaFillPtr fill) { if(fill != m_rectFill) { m_rectFill = fill; for(unsigned int i = 0; i < m_rects.size(); i++) m_rects[i]->setAreaFill(fill); } } unsigned int PlotSelectTool::numSelectedRects() const { return m_rects.size(); } void PlotSelectTool::getSelectedRects(vector<double>& upperLeftXs, vector<double>& upperLeftYs, vector<double>& lowerRightXs, vector<double>& lowerRightYs, PlotCoordinate::System system) const { vector<PlotRegion> v = getSelectedRects(system); upperLeftXs.resize(v.size()); upperLeftYs.resize(v.size()); lowerRightXs.resize(v.size()); lowerRightYs.resize(v.size()); for(unsigned int i = 0; i < v.size(); i++) { upperLeftXs[i] = v[i].upperLeft().x(); upperLeftYs[i] = v[i].upperLeft().y(); lowerRightXs[i] = v[i].lowerRight().x(); lowerRightYs[i] = v[i].lowerRight().y(); } } int PlotSelectTool::getSelectedRectCount(){ return m_rects.size(); } vector<PlotRegion> PlotSelectTool::getSelectedRects(PlotCoordinate::System system) const { vector<PlotRegion> v(m_rects.size()); vector<PlotCoordinate> coords; for(unsigned int i = 0; i < v.size(); i++) { coords = m_rects[i]->coordinates(); // WARNING: assumption that the PlotRectangle implementation behaves // correctly. if(coords[0].system() != system && m_canvas != NULL) coords[0] = m_canvas->convertCoordinate(coords[0], system); if(coords[1].system() != system && m_canvas != NULL) coords[1] = m_canvas->convertCoordinate(coords[1], system); v[i] = PlotRegion(coords[0], coords[1]); } return v; } void PlotSelectTool::clearSelectedRects() { if(m_drawRects && m_canvas != NULL && m_rects.size() > 0) { vector<PlotItemPtr> v(m_rects.size()); for(unsigned int i = 0; i < v.size(); i++) v[i] = m_rects[i]; m_canvas->removePlotItems(v); } m_rects.clear(); } void PlotSelectTool::setActive(bool active) { // We may be acting as either a genuine Select Tool, or as a Subtraction Tool // The distinction is found from m_subtraction_mode // Set line style etc only if different from existing if (active == m_active) return; PlotMouseTool::setActive(active); if (!m_canvas) return; if (active) { if (m_subtraction_mode) { if (!m_subLine.null()) m_canvas->setSelectLine(m_subLine); } else { if (!m_selLine.null()) m_canvas->setSelectLine(m_selLine); } } else { m_canvas->setCursor(NORMAL_CURSOR); } m_canvas->setSelectLineShown(active); } void PlotSelectTool::handleMouseEvent(const PlotEvent& event) { m_lastEventHandled = false; if(m_canvas == NULL || !m_active) return; // shouldn't happen // cursor nice-ness const PlotMousePressEvent* mp; const PlotMouseReleaseEvent* mr; if((mp = dynamic_cast<const PlotMousePressEvent*>(&event)) != NULL) { m_canvas->setCursor(CROSSHAIR); // restore the following lines after figuring out how to make #include <qwt/qwt_plot_picker.h> compile - needs tweak of cmake files ////!!!!! QwtPlotPicker *pp = m_canvas->getSelecter(); // http://www.qtcentre.org/threads/33160-Different-Colored-Rectangles-in-QwtPlotPicker ////!!!!! pp->setRubberBandPen( QColor( Qt::blue ) ); } else if((mr = dynamic_cast<const PlotMouseReleaseEvent*>(&event)) != NULL) { m_canvas->setCursor(NORMAL_CURSOR); } // for now we only care about select events, assuming that the canvas has // done its selection-pen-drawing duty const PlotSelectEvent* select = dynamic_cast<const PlotSelectEvent*>(&event); if(select != NULL && m_canvas != NULL) { PlotRegion r = select->region(); if(r.upperLeft().system() != m_coordSystem || r.lowerRight().system() != m_coordSystem) r = m_canvas->convertRegion(r, m_coordSystem); // The rectangle the user just finished dragging out with the mouse PlotShapeRectanglePtr rect = m_factory->shapeRectangle(r.upperLeft(), r.lowerRight()); if (m_subtraction_mode) { float zapper_x1 = r.upperLeft().x(); float zapper_x2 = r.lowerRight().x(); float zapper_y1 = r.lowerRight().y(); float zapper_y2 = r.upperLeft().y(); int n = m_rects.size(); for (int j=n-1; j>=0; j--) { // test if [j]th rect in our list m_rects fits inside the newly dragged rect PlotShapeRectanglePtr pr = m_rects[j]; vector<PlotCoordinate> coords = pr->coordinates(); float x1 = min(coords[0].x(), coords[1].x() ); float x2 = max(coords[0].x(), coords[1].x() ); float y1 = min(coords[0].y(), coords[1].y() ); float y2 = max(coords[0].y(), coords[1].y() ); bool it_fits = (x1 >= zapper_x1) && (x2 <= zapper_x2) && (y1 >= zapper_y1) && (y2 <= zapper_y2); if (it_fits) { // Must remove both the PlotItem in the canvas and the rect in our list m_canvas->removePlotItem(pr); m_rects.erase( m_rects.begin()+ j); } } #if (0) // testing overlap logic printf("\n\n Post-surgical stats: m_rects n=%d \n\n", (int)m_rects.size() ); #endif m_lastEventHandled = true; } else { // Normal addition of a new region to the list rect->setLine(m_rectLine); rect->setAreaFill(m_rectFill); if(m_drawRects) m_canvas->plotItem(rect, ANNOTATION); m_rects.push_back(rect); m_lastEventHandled = true; } // Whether adding or subtracting regions, notify anyone who asked to be informed for(unsigned int i = 0; i < m_notifiers.size(); i++) m_notifiers[i]->notifySelectionAdded(*this); } } void PlotSelectTool::attach(PlotCanvas* canvas) { PlotMouseTool::attach(canvas); if(canvas != NULL && m_active) { for(unsigned int i = 0; i < m_rects.size(); i++) canvas->drawShape(m_rects[i]); if (m_subtraction_mode) { if(!m_selLine.null()) m_canvas->setSelectLine(m_subLine); else m_canvas->setSelectLineShown(true); } else { if(!m_subLine.null()) m_canvas->setSelectLine(m_selLine); else m_canvas->setSelectLineShown(true); } } } void PlotSelectTool::detach() { if(m_canvas != NULL && m_drawRects && m_rects.size() > 0) { for(unsigned int i = 0; i < m_rects.size(); i++) m_canvas->removeShape(m_rects[i]); } if(m_canvas != NULL) { m_canvas->setCursor(NORMAL_CURSOR); m_canvas->setSelectLineShown(false); } PlotMouseTool::detach(); } ////////////////////////////// // PLOTZOOMTOOL DEFINITIONS // ////////////////////////////// PlotZoomTool::PlotZoomTool(PlotCoordinate::System sys) : PlotMouseTool(sys), m_stack(NULL) { } PlotZoomTool::PlotZoomTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System sys) : PlotMouseTool(xAxis, yAxis, sys), m_stack(NULL) { } PlotZoomTool::~PlotZoomTool() { } void PlotZoomTool::addNotifier(PlotZoomToolNotifier* notifier) { if(notifier == NULL) return; for(unsigned int i = 0; i < m_notifiers.size(); i++) if(m_notifiers[i] == notifier) return; m_notifiers.push_back(notifier); } void PlotZoomTool::setSelectLine(PlotLinePtr line) { if(line != m_selLine) { m_selLine = line; if(m_canvas != NULL) { if(!line.null()) m_canvas->setSelectLine(line); else m_canvas->setSelectLineShown(false); } } } void PlotZoomTool::setSelectLine(bool on) { if(m_canvas != NULL && m_active) m_canvas->setSelectLineShown(on); } vector<PlotRegion> PlotZoomTool::getZoomStack(PlotCoordinate::System s) const { if(m_stack == NULL) return vector<PlotRegion>(); vector<PlotRegion> stack = m_stack->stack(); if(s == m_coordSystem || m_stack->size() == 0 || m_canvas == NULL) return stack; vector<PlotRegion> v(stack.size()); for(unsigned int i = 0; i < v.size(); i++) v[i] = m_canvas->convertRegion(stack[i], s); return v; } unsigned int PlotZoomTool::getStackIndex() const { if(m_stack == NULL) return 0; else return m_stack->stackIndex(); } void PlotZoomTool::setActive(bool active) { if(active != m_active) { PlotMouseTool::setActive(active); if(m_canvas != NULL) { if(active && !m_selLine.null()) m_canvas->setSelectLine(m_selLine); else m_canvas->setSelectLineShown(active); if(!active) m_canvas->setCursor(NORMAL_CURSOR); if(active && m_stack->size() <= 1) m_stack->setBase(m_canvas->axesRanges(m_xAxis, m_yAxis), m_xAxis, m_yAxis); } } } void PlotZoomTool::handleMouseEvent(const PlotEvent& event) { m_lastEventHandled = false; if(m_canvas == NULL || !m_active) return; // cursor nice-ness const PlotMousePressEvent* mp; const PlotMouseReleaseEvent* mr; if((mp = dynamic_cast<const PlotMousePressEvent*>(&event)) != NULL) m_canvas->setCursor(CROSSHAIR); else if((mr = dynamic_cast<const PlotMouseReleaseEvent*>(&event)) != NULL) m_canvas->setCursor(NORMAL_CURSOR); const PlotSelectEvent* s; const PlotWheelEvent* w; const PlotClickEvent* c; // on select: zoom to area if((s = dynamic_cast<const PlotSelectEvent*>(&event)) != NULL) { PlotRegion r = s->region(); if(r.upperLeft().system() != m_coordSystem || r.lowerRight().system() != m_coordSystem) r = m_canvas->convertRegion(r, m_coordSystem); m_stack->addRegion(r, m_xAxis, m_yAxis); if(m_coordSystem != PlotCoordinate::WORLD) r = m_canvas->convertRegion(r, PlotCoordinate::WORLD); m_canvas->setAxesRegion(m_xAxis, m_yAxis, r); m_lastEventHandled = true; // on wheel go through zoom stack } else if((w = dynamic_cast<const PlotWheelEvent*>(&event)) != NULL) { m_canvas->axesStackMove(w->delta()); m_lastEventHandled = true; // go to base on right click, zoom in 50% centered on double click } else if((c = dynamic_cast<const PlotClickEvent*>(&event)) != NULL) { if(c->button() == PlotClickEvent::CONTEXT) { m_canvas->axesStackMove(0); m_lastEventHandled = true; } else if(c->button() == PlotClickEvent::DOUBLE) { prange_t xRange = m_canvas->axisRange(m_xAxis), yRange = m_canvas->axisRange(m_yAxis); double xDelta = (xRange.second - xRange.first) / 4, yDelta = (yRange.second - yRange.first) / 4; PlotCoordinate coord = c->where(); if(coord.system() != PlotCoordinate::WORLD) coord=m_canvas->convertCoordinate(coord,PlotCoordinate::WORLD); PlotRegion r(PlotCoordinate(coord.x()- xDelta, coord.y()+ yDelta), PlotCoordinate(coord.x()+ xDelta, coord.y()- yDelta)); if(m_coordSystem != PlotCoordinate::WORLD) m_stack->addRegion(m_canvas->convertRegion(r, m_coordSystem), m_xAxis, m_yAxis); else m_stack->addRegion(r, m_xAxis, m_yAxis); m_canvas->setAxesRegion(m_xAxis, m_yAxis, r); m_lastEventHandled = true; } } if(m_lastEventHandled) notifyWatchers(); } void PlotZoomTool::reset() { if(m_stack != NULL) m_stack->clearStack(true); } void PlotZoomTool::attach(PlotCanvas* canvas) { PlotMouseTool::attach(canvas); if(canvas != NULL) m_stack = &canvas->axesStack(); if(canvas != NULL && m_active) { if(!m_selLine.null()) m_canvas->setSelectLine(m_selLine); else m_canvas->setSelectLineShown(false); if(m_stack->size() == 0) m_stack->setBase(m_canvas->axesRanges(m_xAxis, m_yAxis), m_xAxis, m_yAxis); } } void PlotZoomTool::detach() { if(m_canvas != NULL) { m_canvas->setCursor(NORMAL_CURSOR); m_canvas->setSelectLineShown(false); } m_stack = NULL; PlotMouseTool::detach(); } void PlotZoomTool::notifyWatchers() { for(unsigned int i = 0; i < m_notifiers.size(); i++) m_notifiers[i]->notifyZoomChanged(*this); } ///////////////////////////// // PLOTPANTOOL DEFINITIONS // ///////////////////////////// PlotPanTool::PlotPanTool(PlotCoordinate::System sys) : PlotMouseTool(sys), m_inDraggingMode(false), m_stack(NULL) { } PlotPanTool::PlotPanTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System sys) : PlotMouseTool(xAxis, yAxis, sys), m_inDraggingMode(false), m_stack(NULL) { } PlotPanTool::~PlotPanTool() { } void PlotPanTool::addNotifier(PlotPanToolNotifier* notifier) { if(notifier == NULL) return; for(unsigned int i = 0; i < m_notifiers.size(); i++) if(m_notifiers[i] == notifier) return; m_notifiers.push_back(notifier); } vector<PlotRegion> PlotPanTool::getPanStack(PlotCoordinate::System s) const { if(m_stack == NULL) return vector<PlotRegion>(); vector<PlotRegion> stack = m_stack->stack(); if(s == m_coordSystem || m_stack->size() == 0 || m_canvas == NULL) return stack; vector<PlotRegion> v(stack.size()); for(unsigned int i = 0; i < v.size(); i++) v[i] = m_canvas->convertRegion(stack[i], s); return v; } unsigned int PlotPanTool::getStackIndex() const { if(m_stack == NULL) return 0; else return m_stack->stackIndex(); } void PlotPanTool::setActive(bool active) { if(active != m_active) { PlotMouseTool::setActive(active); if(m_canvas != NULL) { m_canvas->setCursor(active ? HAND_OPEN : NORMAL_CURSOR); if(active && m_stack->size() == 0) m_stack->setBase(m_canvas->axesRanges(m_xAxis, m_yAxis), m_xAxis, m_yAxis); } } } void PlotPanTool::handleMouseEvent(const PlotEvent& event) { m_lastEventHandled = false; if(m_canvas == NULL) return; const PlotMousePressEvent* mp; const PlotMouseReleaseEvent* mr; const PlotMouseDragEvent* mm; const PlotWheelEvent* w; const PlotClickEvent* c; // dragging if((mp = dynamic_cast<const PlotMousePressEvent*>(&event)) != NULL) { if(mp->button() != PlotClickEvent::SINGLE && mp->button() != PlotClickEvent::DOUBLE) return; m_inDraggingMode = true; m_canvas->setCursor(HAND_CLOSED); m_lastCoord = mp->where(); if(m_lastCoord.system() != PlotCoordinate::WORLD) m_lastCoord = m_canvas->convertCoordinate(m_lastCoord); m_lastEventHandled = true; } else if((mr= dynamic_cast<const PlotMouseReleaseEvent*>(&event))!= NULL){ if(!m_inDraggingMode) return; m_inDraggingMode = false; m_canvas->setCursor(HAND_OPEN); m_stack->addRegion(m_canvas->axesRanges(m_xAxis, m_yAxis), m_xAxis, m_yAxis); m_lastEventHandled = true; } else if((mm = dynamic_cast<const PlotMouseDragEvent*>(&event)) != NULL) { if(!m_inDraggingMode) return; PlotCoordinate c = mm->where(); if(c.system() != PlotCoordinate::WORLD) c = m_canvas->convertCoordinate(c); m_canvas->moveAxesRanges(m_xAxis, m_lastCoord.x() - c.x(), m_yAxis, m_lastCoord.y() - c.y()); m_lastCoord = c; m_lastEventHandled = true; // stack navigation } else if((w = dynamic_cast<const PlotWheelEvent*>(&event)) != NULL) { m_canvas->axesStackMove(w->delta()); m_lastEventHandled = true; } else if((c = dynamic_cast<const PlotClickEvent*>(&event)) != NULL) { if(c->button() == PlotClickEvent::CONTEXT) { m_canvas->axesStackMove(0); m_lastEventHandled = true; } } if(m_lastEventHandled) notifyWatchers(); } void PlotPanTool::reset() { if(m_stack != NULL) m_stack->clearStack(true); } void PlotPanTool::attach(PlotCanvas* canvas) { PlotMouseTool::attach(canvas); if(canvas != NULL) { m_stack = &canvas->axesStack(); if(m_active && m_stack->size() == 0) m_stack->setBase(m_canvas->axesRanges(m_xAxis, m_yAxis), m_xAxis, m_yAxis); } } void PlotPanTool::detach() { if(m_canvas != NULL) m_canvas->setCursor(NORMAL_CURSOR); m_stack = NULL; PlotMouseTool::detach(); } void PlotPanTool::notifyWatchers() { for(unsigned int i = 0; i < m_notifiers.size(); i++) m_notifiers[i]->notifyPanChanged(*this); } ///////////////////////////////// // PLOTTRACKERTOOL DEFINITIONS // ///////////////////////////////// PlotTrackerTool::PlotTrackerTool(PlotCoordinate::System sys) : PlotMouseTool(sys), m_drawText(false), m_format(DEFAULT_FORMAT) { } PlotTrackerTool::PlotTrackerTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System sys) : PlotMouseTool(xAxis, yAxis, sys), m_drawText(false), m_format(DEFAULT_FORMAT) { } PlotTrackerTool::~PlotTrackerTool() { } void PlotTrackerTool::addNotifier(PlotTrackerToolNotifier* notifier) { if(notifier == NULL) return; for(unsigned int i = 0; i < m_notifiers.size(); i++) if(m_notifiers[i] == notifier) return; m_notifiers.push_back(notifier); } void PlotTrackerTool::setDrawText(bool draw) { m_drawText = draw; } bool PlotTrackerTool::drawsText() const { return m_drawText; } void PlotTrackerTool::setFormat(const String& format) { m_format = format; } PlotAnnotationPtr PlotTrackerTool::getAnnotation() { return m_annotation; } PlotCoordinate PlotTrackerTool::getCoordinate(PlotCoordinate::System s) const { if(m_annotation.null() || m_canvas == NULL) return PlotCoordinate(); PlotCoordinate c = m_annotation->coordinate(); if(s == c.system()) return c; else return m_canvas->convertCoordinate(c, s); } void PlotTrackerTool::setActive(bool active) { if(active != m_active) { PlotMouseTool::setActive(active); if(m_canvas != NULL && !m_annotation.null()) m_canvas->removeAnnotation(m_annotation); } } void PlotTrackerTool::handleMouseEvent(const PlotEvent& ev) { m_lastEventHandled = false; if(m_canvas == NULL) return; const PlotMouseMoveEvent* m = dynamic_cast<const PlotMouseMoveEvent*>(&ev); if(m != NULL) { bool autorescale = m_canvas->axesAutoRescale(); if(m_drawText && !m_annotation.null()) { m_canvas->removeAnnotation(m_annotation); m_canvas->setAxesAutoRescale(false); } PlotCoordinate c = m->where(); m_annotation->setCoordinate(c); m_annotation->setText(formattedString(c.x(), c.y())); if(m_drawText) { m_canvas->plotItem(m_annotation, ANNOTATION); m_canvas->setAxesAutoRescale(autorescale); } m_lastEventHandled = true; } if(m_lastEventHandled) notifyWatchers(); } // Protected Methods // void PlotTrackerTool::attach(PlotCanvas* canvas) { PlotMouseTool::attach(canvas); if(m_canvas != NULL) { m_annotation = m_factory->annotation("", PlotCoordinate()); if(m_active) { PlotMouseMoveEventHandlerPtr h(this, false); m_canvas->registerMouseMoveHandler(h, m_coordSystem); } } } void PlotTrackerTool::detach() { if(m_canvas != NULL && m_active) { PlotMouseMoveEventHandlerPtr h(this, false); m_canvas->unregisterMouseMoveHandler(h); m_canvas->removePlotItem(m_annotation); } PlotMouseTool::detach(); m_annotation = NULL; } void PlotTrackerTool::notifyWatchers() { for(unsigned int i = 0; i < m_notifiers.size(); i++) m_notifiers[i]->notifyTrackerChanged(*this); } // Static Members // String PlotTrackerTool::formattedString(const String& format, double x, double y, PlotCanvas* canvas, PlotAxis xAxis, PlotAxis yAxis) { stringstream ss; unsigned int i = 0, j = 0; String token; while(i < format.length()) { // get the next token j = format.find(FORMAT_DIVIDER, i); if(j > i) { if(j < format.size()) { // text between i and token ss << format.substr(i, (j - i)); i = j; } else { // no next tokens ss << format.substr(i); break; } } // i points to the first character of the divider i += FORMAT_DIVIDER.size(); // i points to the first character of the token j = format.find(FORMAT_DIVIDER, i); if(j >= format.size()) { // no closing divider i -= FORMAT_DIVIDER.size(); ss << format.substr(i); break; } token = format.substr(i, (j - i)); i = j + FORMAT_DIVIDER.size(); // i after token if(token == FORMAT_X) { PlotAxisScale scale = canvas->axisScale(xAxis); String format(canvas->dateFormat()); format.gsub("\n", " "); if(scale == DATE_MJ_SEC || scale == DATE_MJ_DAY) ss << Plotter::formattedDateString(format, x, scale); else ss << x; } else if(token == FORMAT_Y) { PlotAxisScale scale = canvas->axisScale(yAxis); String format(canvas->dateFormat()); format.gsub("\n", " "); if(scale == DATE_MJ_SEC || scale == DATE_MJ_DAY) ss << Plotter::formattedDateString(format, y, scale); else ss << y; } else if(token.substr(0, FORMAT_PRECISION.size())== FORMAT_PRECISION){ if(token.size() == FORMAT_PRECISION.size()) // invalid ss << FORMAT_DIVIDER << FORMAT_PRECISION << FORMAT_DIVIDER; else { token = token.substr(FORMAT_PRECISION.size()); int prec; if(sscanf(token.c_str(), "%d", &prec) == 1) ss << setprecision(prec); else // invalid ss << FORMAT_DIVIDER << FORMAT_PRECISION << token << FORMAT_DIVIDER; } } else { // not a valid token ss << FORMAT_DIVIDER << token << FORMAT_DIVIDER; } } return ss.str(); } const String PlotTrackerTool::FORMAT_DIVIDER = "%%"; const String PlotTrackerTool::FORMAT_X = "x"; const String PlotTrackerTool::FORMAT_Y = "y"; const String PlotTrackerTool::FORMAT_PRECISION = "p"; const String PlotTrackerTool::DEFAULT_FORMAT = "("+FORMAT_DIVIDER+FORMAT_X+ FORMAT_DIVIDER + ", " + FORMAT_DIVIDER+FORMAT_Y+FORMAT_DIVIDER + ")"; ///////////////////////////////// // PLOTFLAGALLTOOL DEFINITIONS // ///////////////////////////////// PlotFlagAllTool::PlotFlagAllTool(PlotCoordinate::System sys) : PlotMouseTool(sys), m_draw(true), m_bgcolor_changed(false), m_marked(PlotFlagAllTool::PPFLAG_NONE), m_defaultBackground(NULL) { } PlotFlagAllTool::PlotFlagAllTool(PlotAxis xAxis, PlotAxis yAxis, PlotCoordinate::System sys) : PlotMouseTool(xAxis, yAxis, sys), m_draw(true), m_bgcolor_changed(false), m_marked(PlotFlagAllTool::PPFLAG_NONE), m_defaultBackground(NULL) { } PlotFlagAllTool::~PlotFlagAllTool() { } void PlotFlagAllTool::setUpdateBackground(bool on) { m_draw = on; } bool PlotFlagAllTool::isUpdateBackgroundActive() { return m_draw; } void PlotFlagAllTool::clearMark() { m_marked = PlotFlagAllTool::PPFLAG_NONE; m_bgcolor_changed = false; } bool PlotFlagAllTool::isMarkedForFlag() const { return m_marked == PlotFlagAllTool::PPFLAG_FLAG; } bool PlotFlagAllTool::isMarkedForUnflag() const { return m_marked == PlotFlagAllTool::PPFLAG_UNFLAG; } bool PlotFlagAllTool::isBackgroundColorChanged() const { return m_bgcolor_changed; } void PlotFlagAllTool::setAllFlagged() { m_canvas->setBackground("yellow", PlotAreaFill::MESH1); m_bgcolor_changed = true; } void PlotFlagAllTool::markAsFlag() { if (m_draw) { m_canvas->setBackground("yellow", PlotAreaFill::MESH1); m_bgcolor_changed = true; } m_marked = PlotFlagAllTool::PPFLAG_FLAG; } void PlotFlagAllTool::markAsUnflag() { if (m_draw) { m_canvas->setBackground(m_defaultBackground); m_bgcolor_changed = false; } m_marked = PlotFlagAllTool::PPFLAG_UNFLAG; } void PlotFlagAllTool::handleMouseEvent(const PlotEvent& event) { m_lastEventHandled = false; if(m_canvas == NULL) return; const PlotClickEvent *c = dynamic_cast<const PlotClickEvent*>(&event); if(c != NULL) { // get default background setting auto const canvas = c->canvas(); // do nothing if canvas is empty if (canvas->title().empty()) { return; } if (m_defaultBackground.null()) { m_defaultBackground = canvas->defaultBackground(); } // mark canvas and change background switch (m_marked) { case PlotFlagAllTool::PPFLAG_FLAG: markAsUnflag(); break; case PlotFlagAllTool::PPFLAG_UNFLAG: markAsFlag(); break; default: if (m_bgcolor_changed) { markAsUnflag(); } else { markAsFlag(); } break; } m_canvas->refresh(); m_lastEventHandled = true; } } //////////////////////////////////// // PLOTMOUSETOOLGROUP DEFINITIONS // //////////////////////////////////// // Public Methods // PlotMouseToolGroup::PlotMouseToolGroup() { } PlotMouseToolGroup::~PlotMouseToolGroup() { } unsigned int PlotMouseToolGroup::numTools() const { return m_tools.size(); } vector<PlotMouseToolPtr> PlotMouseToolGroup::tools() const { return m_tools; } unsigned int PlotMouseToolGroup::addTool(PlotMouseToolPtr tool) { if(tool.null()) return m_tools.size(); for(unsigned int i = 0; i < m_tools.size(); i++) if(m_tools[i] == tool) return i; m_tools.push_back(tool); if(m_canvas != NULL) tool->attach(m_canvas); // bookkeeping: blocking, active, active tool tool->setBlocking(m_blocking); tool->setActive(false); return m_tools.size() - 1; } bool PlotMouseToolGroup::removeTool(PlotMouseToolPtr tool) { if (tool.null()) return false; for (unsigned int i = 0; i < m_tools.size(); i++) { if (m_tools[i] == tool) { m_tools.erase(m_tools.begin() + i); if (tool == m_activeTool) { if (m_tools.size() > 0) setActiveTool(m_tools[0]); else m_activeTool = PlotMouseToolPtr(); } return true; } } return false; } PlotMouseToolPtr PlotMouseToolGroup::toolAt(unsigned int index) const { if(index < m_tools.size()) return m_tools[index]; else return PlotMouseToolPtr(); } unsigned int PlotMouseToolGroup::indexOf(PlotMouseToolPtr tool) const { if(tool.null()) return m_tools.size(); for(unsigned int i = 0; i < m_tools.size(); i++) if(m_tools[i] == tool) return i; return m_tools.size(); } void PlotMouseToolGroup::setActiveTool(PlotMouseToolPtr tool, ToolCode toolcode) { addTool(tool); m_activeTool = tool; /* FIND-ME DEBUG - DSW 878*/ for (unsigned int i = 0; i < m_tools.size(); i++) m_tools[i]->setActive(false); if (!tool.null()) { PlotSelectTool* seltool = dynamic_cast<PlotSelectTool*> (&*tool); if (seltool!=NULL) { seltool->m_subtraction_mode = (toolcode==SUBTRACT_TOOL); } tool->setActive(m_active); } } void PlotMouseToolGroup::setActive(bool isActive) { PlotMouseTool::setActive(isActive); if(!m_activeTool.null()) m_activeTool->setActive(isActive); } void PlotMouseToolGroup::setBlocking(bool blocking) { PlotMouseTool::setBlocking(blocking); for(unsigned int i = 0; i < m_tools.size(); i++) m_tools[i]->setBlocking(blocking); } void PlotMouseToolGroup::handleMouseEvent(const PlotEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleMouseEvent(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleSelect(const PlotSelectEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleSelect(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleClick(const PlotClickEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleClick(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleMousePress(const PlotMousePressEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleMousePress(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleMouseRelease(const PlotMouseReleaseEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleMouseRelease(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleMouseDrag(const PlotMouseDragEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleMouseDrag(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleMouseMove(const PlotMouseMoveEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleMouseMove(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } void PlotMouseToolGroup::handleWheel(const PlotWheelEvent& event) { if(m_active && !m_activeTool.null()) { m_activeTool->handleWheel(event); m_lastEventHandled = m_activeTool->lastEventWasHandled(); } else m_lastEventHandled = false; } PlotAxis PlotMouseToolGroup::getXAxis() const { if(!m_activeTool.null()) return m_activeTool->getXAxis(); else if(m_tools.size() > 0) return m_tools[0]->getXAxis(); else return m_xAxis; } PlotAxis PlotMouseToolGroup::getYAxis() const { if(!m_activeTool.null()) return m_activeTool->getYAxis(); else if(m_tools.size() > 0) return m_tools[0]->getYAxis(); else return m_yAxis; } PlotCoordinate::System PlotMouseToolGroup::getCoordinateSystem() const { if(!m_activeTool.null()) return m_activeTool->getCoordinateSystem(); else if(m_tools.size() > 0) return m_tools[0]->getCoordinateSystem(); else return m_coordSystem; } bool PlotMouseToolGroup::lastEventWasHandled() const { if(!m_activeTool.null()) return m_activeTool->lastEventWasHandled(); else return false; } void PlotMouseToolGroup::reset() { for(unsigned int i = 0; i < m_tools.size(); i++) { m_tools[i]->reset(); } } // Protected Methods // void PlotMouseToolGroup::attach(PlotCanvas* canvas) { PlotMouseTool::attach(canvas); for(unsigned int i = 0; i< m_tools.size(); i++) m_tools[i]->attach(canvas); } void PlotMouseToolGroup::detach() { PlotMouseTool::detach(); for(unsigned int i = 0; i < m_tools.size(); i++) m_tools[i]->detach(); } //////////////////////////////////////////// // PLOTSTANDARDMOUSETOOLGROUP DEFINITIONS // //////////////////////////////////////////// PlotStandardMouseToolGroup::PlotStandardMouseToolGroup(ToolCode activeTool, PlotCoordinate::System system) { addTool(new PlotSelectTool(system)); addTool(new PlotZoomTool(system)); addTool(new PlotPanTool(system)); addTool(new PlotFlagAllTool(system)); setActiveTool(activeTool); m_tracker = new PlotTrackerTool(system); m_tracker->setBlocking(false); m_coordSystem = system; } PlotStandardMouseToolGroup::PlotStandardMouseToolGroup(PlotAxis xAxis, PlotAxis yAxis, ToolCode activeTool, PlotCoordinate::System system) { addTool(new PlotSelectTool(xAxis, yAxis, system)); addTool(new PlotZoomTool(xAxis, yAxis, system)); addTool(new PlotPanTool(xAxis, yAxis, system)); addTool(new PlotFlagAllTool(xAxis, yAxis, system)); setActiveTool(activeTool); m_tracker = new PlotTrackerTool(xAxis, yAxis, system); m_tracker->setBlocking(false); m_xAxis = xAxis; m_yAxis = yAxis; m_coordSystem = system; } PlotStandardMouseToolGroup::PlotStandardMouseToolGroup( PlotSelectToolPtr selectTool, PlotZoomToolPtr zoomTool, PlotPanToolPtr panTool, PlotFlagAllToolPtr flagAllTool, PlotTrackerToolPtr trackerTool, ToolCode activeTool) { addTool(!selectTool.null() ? selectTool : new PlotSelectTool()); addTool(!zoomTool.null() ? zoomTool : new PlotZoomTool()); addTool(!panTool.null() ? panTool : new PlotPanTool()); addTool(!flagAllTool.null() ? flagAllTool : new PlotFlagAllTool()); setActiveTool(activeTool); m_tracker = !trackerTool.null() ? trackerTool : new PlotTrackerTool(); m_tracker->setBlocking(false); } PlotStandardMouseToolGroup::~PlotStandardMouseToolGroup() { } void PlotStandardMouseToolGroup::setActiveTool(ToolCode toolcode) { if(toolcode == NONE_TOOL) { PlotMouseToolGroup::setActiveTool(PlotMouseToolPtr()); return; } for(unsigned int i = 0; i < m_tools.size(); i++) { if (((dynamic_cast<PlotSelectTool*>(&*m_tools[i]) != NULL && toolcode==SELECT_TOOL)) || ((dynamic_cast<PlotSelectTool*>(&*m_tools[i]) != NULL && toolcode==SUBTRACT_TOOL)) || ((dynamic_cast<PlotZoomTool*>(&*m_tools[i]) != NULL && toolcode==ZOOM_TOOL)) || ((dynamic_cast<PlotPanTool*>(&*m_tools[i]) != NULL) && toolcode==PAN_TOOL) || ((dynamic_cast<PlotFlagAllTool*>(&*m_tools[i]) != NULL) && toolcode == FLAGALL_TOOL)) { PlotMouseToolGroup::setActiveTool(i, toolcode); return; } } } ToolCode PlotStandardMouseToolGroup::activeToolType() const { if(m_activeTool.null()) return NONE_TOOL; if(dynamic_cast<const PlotSelectTool*>(&*m_activeTool)!=NULL) return SELECT_TOOL; if(dynamic_cast<const PlotZoomTool*>(&*m_activeTool) != NULL) return ZOOM_TOOL; if(dynamic_cast<const PlotPanTool*>(&*m_activeTool) != NULL) return PAN_TOOL; return NONE_TOOL; } void PlotStandardMouseToolGroup::turnTracker(bool on) { m_tracker->setActive(on); } bool PlotStandardMouseToolGroup::trackerIsOn() const { return m_tracker->isActive(); } void PlotStandardMouseToolGroup::turnTrackerDrawText(bool on) { m_tracker->setDrawText(on); } bool PlotStandardMouseToolGroup::trackerDrawsText() const { return m_tracker->drawsText(); } int PlotStandardMouseToolGroup::getSelectedRectCount(){ PlotSelectToolPtr selectPtr = selectTool(); int rectCount = selectPtr->getSelectedRectCount(); return rectCount; } void PlotStandardMouseToolGroup::clearSelectedRects(){ PlotSelectToolPtr selectPtr = selectTool(); selectPtr->clearSelectedRects(); } vector<PlotRegion> PlotStandardMouseToolGroup::getSelectedRects(){ PlotSelectToolPtr selectPtr = selectTool(); vector<PlotRegion> regions = selectPtr->getSelectedRects(); return regions; } void PlotStandardMouseToolGroup::clearMark() { auto ptr = flagAllTool(); ptr->clearMark(); } bool PlotStandardMouseToolGroup::isMarkedForFlag() { auto ptr = flagAllTool(); return ptr->isMarkedForFlag(); } bool PlotStandardMouseToolGroup::isMarkedForUnflag() { auto ptr = flagAllTool(); return ptr->isMarkedForUnflag(); } bool PlotStandardMouseToolGroup::isBackgroundColorChanged() { auto ptr = flagAllTool(); return ptr->isBackgroundColorChanged(); } void PlotStandardMouseToolGroup::setAllFlagged() { auto ptr = flagAllTool(); ptr->setAllFlagged(); } PlotSelectToolPtr PlotStandardMouseToolGroup::selectTool() { for(unsigned int i = 0; i < m_tools.size(); i++) if(dynamic_cast<PlotSelectTool*>(&*m_tools[i]) != NULL) return PlotSelectToolPtr(m_tools[i]); // shouldn't happen! PlotSelectToolPtr t = new PlotSelectTool(); m_tools.push_back(t); return t; } PlotZoomToolPtr PlotStandardMouseToolGroup::zoomTool() { for(unsigned int i = 0; i < m_tools.size(); i++) if(dynamic_cast<PlotZoomTool*>(&*m_tools[i]) != NULL) return PlotZoomToolPtr(m_tools[i]); // shouldn't happen! PlotZoomToolPtr t = new PlotZoomTool(); m_tools.push_back(t); return t; } PlotPanToolPtr PlotStandardMouseToolGroup::panTool() { for(unsigned int i = 0; i < m_tools.size(); i++) if(dynamic_cast<PlotPanTool*>(&*m_tools[i]) != NULL) return PlotPanToolPtr(m_tools[i]); // shouldn't happen! PlotPanToolPtr t = new PlotPanTool(); m_tools.push_back(t); return t; } PlotFlagAllToolPtr PlotStandardMouseToolGroup::flagAllTool() { for(unsigned int i = 0; i < m_tools.size(); i++) if(dynamic_cast<PlotFlagAllTool*>(&*m_tools[i]) != NULL) return PlotFlagAllToolPtr(m_tools[i]); // shouldn't happen! PlotFlagAllToolPtr t = new PlotFlagAllTool(); m_tools.push_back(t); return t; } PlotTrackerToolPtr PlotStandardMouseToolGroup::trackerTool() { return m_tracker; } // Protected Methods // void PlotStandardMouseToolGroup::attach(PlotCanvas* canvas) { PlotMouseToolGroup::attach(canvas); m_tracker->attach(canvas); } void PlotStandardMouseToolGroup::detach() { PlotMouseToolGroup::detach(); m_tracker->detach(); } } // namespace