//# PlotCanvas.cc: Main drawing area for different plot items to be attached. //# Copyright (C) 2009 //# 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/PlotCanvas.h> #include <graphics/GenericPlotter/PlotFactory.h> #include <graphics/GenericPlotter/PlotOptions.h> using namespace std; using namespace casacore; namespace casa { //////////////////////////// // PLOTCANVAS DEFINITIONS // //////////////////////////// // Static // vector<PlotCanvas::LegendPosition> PlotCanvas::allLegendPositions() { static vector<LegendPosition> v(8); v[0] = INT_URIGHT; v[1] = INT_LRIGHT; v[2] = INT_ULEFT; v[3] = INT_LLEFT; v[4] = EXT_RIGHT; v[5] = EXT_TOP; v[6] = EXT_LEFT; v[7] = EXT_BOTTOM; return v; } vector<String> PlotCanvas::allLegendPositionStrings() { static vector<LegendPosition> p = allLegendPositions(); static vector<String> v(p.size()); for(unsigned int i = 0; i < v.size(); i++) v[i] = legendPosition(p[i]); return v; } String PlotCanvas::legendPosition(LegendPosition p) { switch(p) { case INT_URIGHT: return "Upper Right"; case INT_LRIGHT: return "Lower Right"; case INT_ULEFT: return "Upper Left"; case INT_LLEFT: return "Lower Left"; case EXT_RIGHT: return "Out Right"; case EXT_TOP: return "Out Top"; case EXT_LEFT: return "Out Left"; case EXT_BOTTOM: return "Out Bottom"; default: return ""; } } PlotCanvas::LegendPosition PlotCanvas::legendPosition(String p, bool* ok) { p.downcase(); if(ok != NULL) *ok = true; if(p == "upper right") return INT_URIGHT; else if(p == "upper left") return INT_ULEFT; else if(p == "lower right") return INT_LRIGHT; else if(p == "lower left") return INT_LLEFT; else if(p == "out right") return EXT_RIGHT; else if(p == "out left") return EXT_LEFT; else if(p == "out top") return EXT_TOP; else if(p == "out bottom") return EXT_BOTTOM; if(ok != NULL) *ok = false; return INT_URIGHT; } bool PlotCanvas::legendPositionIsInternal(LegendPosition p) { return p == INT_URIGHT || p == INT_ULEFT || p == INT_LRIGHT || p == INT_LLEFT; } vector<PlotAxis> PlotCanvas::allAxes() { vector<PlotAxis> v(4); v[0] = X_BOTTOM; v[1] = X_TOP; v[2] = Y_LEFT; v[3] = Y_RIGHT; return v; } int PlotCanvas::allAxesFlag() { int flag = 0; vector<PlotAxis> v = allAxes(); for(unsigned int i = 0; i < v.size(); i++) flag |= v[i]; return flag; } vector<PlotCanvasLayer> PlotCanvas::allLayers() { vector<PlotCanvasLayer> v(2); v[0] = MAIN; v[1] = ANNOTATION; return v; } int PlotCanvas::allLayersFlag() { int flag = 0; vector<PlotCanvasLayer> v = allLayers(); for(unsigned int i = 0; i < v.size(); i++) flag |= v[i]; return flag; } const String PlotCanvas::OPERATION_DRAW = "draw_items"; const String PlotCanvas::OPERATION_EXPORT = "export"; // Non-Static // PlotCanvas::PlotCanvas() { } PlotCanvas::~PlotCanvas() { // Calling this here results in a pure virtual method exception. // Virtual methods in constructors and destructors do not resolve! //operationDraw()->finish(); } bool PlotCanvas::hasSelectedRectangles(){ bool selectedRectangles = false; if ( !m_standardTools.null() ){ int rectCount = m_standardTools->getSelectedRectCount(); if ( rectCount > 0 ){ selectedRectangles = true; } } return selectedRectangles; } vector<PlotRegion> PlotCanvas::getSelectedRects(){ vector<PlotRegion> regions; if ( !m_standardTools.null()){ regions = m_standardTools->getSelectedRects(); } return regions; } void PlotCanvas::clearSelectedRects(){ if ( !m_standardTools.null()){ m_standardTools->clearSelectedRects(); } } void PlotCanvas::clearMark() { if (!m_standardTools.null()) { m_standardTools->clearMark(); } } bool PlotCanvas::isMarkedForFlag() { return (!m_standardTools.null()) ? m_standardTools->isMarkedForFlag() : false; } bool PlotCanvas::isMarkedForUnflag() { return (!m_standardTools.null()) ? m_standardTools->isMarkedForUnflag() : false; } bool PlotCanvas::isBackgroundColorChanged() { return (!m_standardTools.null()) ? m_standardTools->isBackgroundColorChanged() : false; } void PlotCanvas::setAllFlagged() { if (!m_standardTools.null()) { m_standardTools->setAllFlagged(); } } bool PlotCanvas::hasThreadedDrawing() const { PlotFactory* f = implementationFactory(); bool ret = f != NULL && f->canvasHasThreadedDrawing(); delete f; return ret; } bool PlotCanvas::hasCachedLayerDrawing() const { PlotFactory* f = implementationFactory(); bool ret = f != NULL && f->canvasHasCachedLayerDrawing(); delete f; return ret; } bool PlotCanvas::hasCachedAxesStack() const { PlotFactory* f = implementationFactory(); bool ret = f != NULL && f->canvasHasCachedAxesStack(); delete f; return ret; } void PlotCanvas::setTitleFont(const PlotFontPtr font) { if(!font.null()) setTitleFont(*font); } PlotAreaFillPtr PlotCanvas::defaultBackground() const { return PlotAreaFillPtr(nullptr); } void PlotCanvas::setBackground(const PlotAreaFillPtr areaFill) { if(!areaFill.null()) setBackground(*areaFill); } void PlotCanvas::setBackground(const String& color, PlotAreaFill::Pattern pattern) { PlotAreaFillPtr bg = background(); bg->setColor(color); bg->setPattern(pattern); setBackground(*bg); } bool PlotCanvas::isAxisShown(PlotAxis axis) const { return shownAxes() & axis; } /* DSW: SITE OF X-Y SHORTCIRCUIT */ void PlotCanvas::showAxis(PlotAxis axis, bool show) { PlotAxisBitset axes = shownAxes(); if (show) axes |= (PlotAxisBitset)axis; else axes &= ~(PlotAxisBitset)axis; showAxes(axes); /* calls QPCanvas::showAxes() */ } void PlotCanvas::showAxes(PlotAxis xAxis, PlotAxis yAxis, bool show) { PlotAxisBitset combined = ( ((PlotAxisBitset)xAxis) | ((PlotAxisBitset)yAxis) ); PlotAxisBitset axes = shownAxes(); if (show) axes |= combined; else axes &= ~combined; showAxes(axes); /* calls casaqt's QPCanvas::showAxes() */ } void PlotCanvas::showAllAxes(bool show) { if(show) showAxes(X_BOTTOM | X_TOP | Y_LEFT | Y_RIGHT); else showAxes(0); } void PlotCanvas::setAxesScales(PlotAxis xAxis, PlotAxisScale xScale, PlotAxis yAxis, PlotAxisScale yScale) { setAxisScale(xAxis, xScale); setAxisScale(yAxis, yScale); } void PlotCanvas::showCartesianAxis(PlotAxis mirrorAxis, bool show, bool hideNormalAxis) { switch(mirrorAxis) { case X_BOTTOM: case X_TOP: showCartesianAxis(mirrorAxis, Y_LEFT, show, hideNormalAxis); break; case Y_LEFT: case Y_RIGHT: showCartesianAxis(mirrorAxis, X_BOTTOM, show, hideNormalAxis); break; } } void PlotCanvas::showCartesianAxes(bool show, bool hideNormal) { showCartesianAxis(X_BOTTOM, show, hideNormal); showCartesianAxis(Y_LEFT, show, hideNormal); } void PlotCanvas::clearAxesLabels() { setAxisLabel(X_BOTTOM, ""); setAxisLabel(X_TOP, ""); setAxisLabel(Y_LEFT, ""); setAxisLabel(Y_RIGHT, ""); } void PlotCanvas::setAxisFont(PlotAxis axis, const PlotFontPtr font) { if(!font.null()) setAxisFont(axis, *font); } PlotRegion PlotCanvas::axesRanges(PlotAxis xAxis, PlotAxis yAxis) const { prange_t x = axisRange(xAxis), y = axisRange(yAxis); return PlotRegion(PlotCoordinate(x.first, y.second), PlotCoordinate(x.second, y.first)); } void PlotCanvas::setAxisRange(PlotAxis axis, const prange_t& range){ setAxisRange(axis, range.first, range.second); } void PlotCanvas::setAxesRanges(PlotAxis xAxis, double xFrom, double xTo, PlotAxis yAxis, double yFrom, double yTo) { setAxisRange(xAxis, xFrom, xTo); setAxisRange(yAxis, yFrom, yTo); } void PlotCanvas::setAxesRanges(PlotAxis xAxis, const prange_t& xRange, PlotAxis yAxis, const prange_t& yRange) { setAxesRanges(xAxis, xRange.first, xRange.second, yAxis, yRange.first, yRange.second); } void PlotCanvas::setAxesRegion(PlotAxis xAxis, PlotAxis yAxis, const PlotRegion& region) { PlotRegion r = region; if(region.upperLeft().system() != PlotCoordinate::WORLD || region.lowerRight().system() != PlotCoordinate::WORLD) r = convertRegion(region, PlotCoordinate::WORLD); setAxesRanges(xAxis, region.upperLeft().x(), region.lowerRight().x(), yAxis, region.lowerRight().y(), region.upperLeft().y()); } void PlotCanvas::moveAxisRange(PlotAxis axis, double delta) { prange_t r = axisRange(axis); r.first += delta; r.second += delta; setAxisRange(axis, r.first, r.second); } void PlotCanvas::moveAxesRanges(PlotAxis xAxis, double xDelta, PlotAxis yAxis, double yDelta) { prange_t x = axisRange(xAxis), y = axisRange(yAxis); x.first += xDelta; x.second += xDelta; y.first += yDelta; y.second += yDelta; setAxesRanges(xAxis, x.first, x.second, yAxis, y.first, y.second); } PlotAxesStack& PlotCanvas::axesStack() { return m_stack; } const PlotAxesStack& PlotCanvas::axesStack() const { return m_stack; } bool PlotCanvas::axesStackMove(int delta) { PlotAxesStack& stack = axesStack(); if(!stack.isValid()) return false; unsigned int index = stack.stackIndex(), size = stack.size(); if(size == 1 || (delta <= 0 && index == 0) || (delta > 0 && index == size - 1)) return false; PlotRegion r = convertRegion(stack.moveAndReturn(delta), PlotCoordinate::WORLD); setAxesRegion(stack.currentXAxis(), stack.currentYAxis(), r); return true; } int PlotCanvas::axesStackLengthLimit() const { return axesStack().lengthLimit(); } void PlotCanvas::setAxesStackLengthLimit(int lengthLimit) { axesStack().setLengthLimit(lengthLimit); } pair<int, int> PlotCanvas::cachedAxesStackImageSize() const { return pair<int, int>(-1, -1); } void PlotCanvas::setCachedAxesStackImageSize(int width, int height) { (void)width, (void)height; } bool PlotCanvas::plot(PlotPtr plot, bool overplot) { if(!overplot) clearPlots(); return plotItem(plot, MAIN); } bool PlotCanvas::plotPoint(PlotPointPtr point){ return plotItem(point, MAIN); } bool PlotCanvas::drawShape(PlotShapePtr shape){ return plotItem(shape, MAIN); } bool PlotCanvas::drawAnnotation(PlotAnnotationPtr annotation) { return plotItem(annotation, MAIN); } // Macro for common method definitions. #define PC_ALL(ITEM,CLASS) \ vector< CLASS##Ptr > PlotCanvas::all##ITEM##s() const { \ vector<PlotItemPtr> v = allPlotItems(); \ vector< CLASS##Ptr > v2; \ for(unsigned int i = 0; i < v.size(); i++) \ if(!v[i].null() && dynamic_cast< CLASS *>(&*v[i]) != NULL) \ v2.push_back(v[i]); \ return v2; \ } \ \ vector< CLASS##Ptr > PlotCanvas::layer##ITEM##s(PlotCanvasLayer layer) const {\ vector<PlotItemPtr> v = layerPlotItems(layer); \ vector< CLASS##Ptr > v2; \ for(unsigned int i = 0; i < v.size(); i++) \ if(!v[i].null() && dynamic_cast< CLASS *>(&*v[i]) != NULL) \ v2.push_back(v[i]); \ return v2; \ } \ \ void PlotCanvas::removeLast##ITEM () { \ vector< CLASS##Ptr > v = all##ITEM##s(); \ for(int i = v.size() - 1; i >= 0; i--) { \ if(!v[i].null()) { \ removePlotItem(v[i]); \ break; \ } \ } \ } \ \ void PlotCanvas::clear##ITEM##s() { \ vector< CLASS##Ptr > v = all##ITEM##s(); \ vector<PlotItemPtr> v2(v.size()); \ for(unsigned int i = 0; i < v.size(); i++) v2[i] = v[i]; \ removePlotItems(v2); \ } PC_ALL(Plot, Plot) PC_ALL(Point, PlotPoint) PC_ALL(Shape, PlotShape) PC_ALL(Annotation, PlotAnnotation) unsigned int PlotCanvas::numPlotItems() const { return allPlotItems().size(); } unsigned int PlotCanvas::numPlots() const { return allPlots().size(); } unsigned int PlotCanvas::numPoints() const { return allPoints().size(); } unsigned int PlotCanvas::numShapes() const { return allShapes().size(); } unsigned int PlotCanvas::numAnnotations() const { return allAnnotations().size(); } unsigned int PlotCanvas::numLayerPlotItems(PlotCanvasLayer layer) const { return layerPlotItems(layer).size(); } unsigned int PlotCanvas::numLayerPlots(PlotCanvasLayer layer) const { return layerPlots(layer).size(); } unsigned int PlotCanvas::numLayerPoints(PlotCanvasLayer layer) const { return layerPoints(layer).size(); } unsigned int PlotCanvas::numLayerShapes(PlotCanvasLayer layer) const { return layerShapes(layer).size(); } unsigned int PlotCanvas::numLayerAnnotations(PlotCanvasLayer layer) const { return layerAnnotations(layer).size(); } void PlotCanvas::removePlotItem(PlotItemPtr item) { if(!item.null()) removePlotItems(vector<PlotItemPtr>(1, item)); } void PlotCanvas::removePlot(PlotPtr plot) { removePlotItem(plot); } void PlotCanvas::removePoint(PlotPointPtr point) { removePlotItem(point); } void PlotCanvas::removeShape(PlotShapePtr shape) { removePlotItem(shape); } void PlotCanvas::removeAnnotation(PlotAnnotationPtr annotation) { removePlotItem(annotation); } void PlotCanvas::removeLastPlotItem() { vector<PlotItemPtr> v = allPlotItems(); for(int i = v.size() - 1; i >= 0; i--) { if(!v[i].null()) { removePlotItem(v[i]); break; } } } void PlotCanvas::clearItems() { removePlotItems(allPlotItems()); } void PlotCanvas::clearLayer(PlotCanvasLayer layer) { removePlotItems(layerPlotItems(layer)); } PlotOperationPtr PlotCanvas::operationDraw() { return operationDraw(PlotMutexPtr()); } PlotOperationPtr PlotCanvas::operationDraw(PlotMutexPtr m) { if(m_drawOperation.null()) m_drawOperation = new PlotOperation(OPERATION_DRAW, mutex()); if(!m.null()) m_drawOperation->setMutex(m); return m_drawOperation; } void PlotCanvas::registerDrawWatcher(PlotDrawWatcherPtr watcher) { if(watcher.null()) return; for(unsigned int i = 0; i < m_drawWatchers.size(); i++) if(m_drawWatchers[i] == watcher) return; m_drawWatchers.push_back(watcher); } void PlotCanvas::unregisterDrawWatcher(PlotDrawWatcherPtr watcher) { if(watcher.null()) return; for(unsigned int i = 0; i < m_drawWatchers.size(); i++) { if(m_drawWatchers[i] == watcher) { m_drawWatchers.erase(m_drawWatchers.begin() + i); return; } } } bool PlotCanvas::selectLineShown() const { PlotLinePtr line = selectLine(); return !line.null() && line->style() != PlotLine::NOLINE; } void PlotCanvas::setSelectLine(const PlotLinePtr line) { if(!line.null()) setSelectLine(*line); else setSelectLineShown(false); } void PlotCanvas::setSelectLine(const String& color, PlotLine::Style style, double width) { PlotLinePtr line = selectLine(); line->setColor(color); line->setStyle(style); line->setWidth(width); setSelectLine(*line); } void PlotCanvas::showGrid(bool showAll) { showGrid(showAll, showAll, showAll, showAll); } void PlotCanvas::showGridMajor(bool show) { showGrid(show, gridXMinorShown(), show, gridYMinorShown()); } void PlotCanvas::showGridMinor(bool show) { showGrid(gridXMajorShown(), show, gridYMajorShown(), show); } bool PlotCanvas::gridXMajorShown() const { bool show; gridShown(&show); return show; } void PlotCanvas::showGridXMajor(bool s) { showGrid(s, gridXMinorShown(), gridYMajorShown(), gridYMinorShown()); } bool PlotCanvas::gridXMinorShown() const { bool show; gridShown(NULL, &show); return show; } void PlotCanvas::showGridXMinor(bool s) { showGrid(gridXMajorShown(), s, gridYMajorShown(), gridYMinorShown()); } bool PlotCanvas::gridYMajorShown() const { bool show; gridShown(NULL, NULL, &show); return show; } void PlotCanvas::showGridYMajor(bool s) { showGrid(gridXMajorShown(), gridXMinorShown(), s, gridYMinorShown()); } bool PlotCanvas::gridYMinorShown() const { bool show; gridShown(NULL, NULL, NULL, &show); return show; } void PlotCanvas::showGridYMinor(bool s) { showGrid(gridXMajorShown(), gridXMinorShown(), gridYMajorShown(), s); } void PlotCanvas::setGridMajorLine(const PlotLinePtr line) { if(!line.null()) setGridMajorLine(*line); else showGridMajor(false); } void PlotCanvas::setGridMajorLine(const String& color, PlotLine::Style style, double width) { PlotLinePtr line = gridMajorLine(); line->setColor(color); line->setStyle(style); line->setWidth(width); setGridMajorLine(*line); } void PlotCanvas::setGridMinorLine(const PlotLinePtr line) { if(!line.null()) setGridMinorLine(*line); else showGridMinor(false); } void PlotCanvas::setGridMinorLine(const String& color, PlotLine::Style style, double width) { PlotLinePtr line = gridMinorLine(); line->setColor(color); line->setStyle(style); line->setWidth(width); setGridMinorLine(*line); } void PlotCanvas::setLegendLine(const PlotLinePtr line) { if(!line.null()) setLegendLine(*line); else setLegendLine("000000", PlotLine::NOLINE); } void PlotCanvas::setLegendLine(const String& color, PlotLine::Style style, double width) { PlotLinePtr line = legendLine(); line->setColor(color); line->setStyle(style); line->setWidth(width); setLegendLine(*line); } void PlotCanvas::setLegendFill(const PlotAreaFillPtr area) { if(!area.null()) setLegendFill(*area); else setLegendFill("000000", PlotAreaFill::NOFILL); } void PlotCanvas::setLegendFill(const String& color, PlotAreaFill::Pattern pattern) { PlotAreaFillPtr fill = legendFill(); fill->setColor(color); fill->setPattern(pattern); setLegendFill(*fill); } void PlotCanvas::setLegendFont(const PlotFontPtr font) { if(!font.null()) setLegendFont(*font); } PlotOperationPtr PlotCanvas::operationExport() { return operationExport(PlotMutexPtr()); } PlotOperationPtr PlotCanvas::operationExport(PlotMutexPtr m) { if(m_exportOperation.null()) m_exportOperation = new PlotOperation(OPERATION_EXPORT, mutex()); if(!m.null()) m_exportOperation->setMutex(m); return m_exportOperation; } PlotRegion PlotCanvas::convertRegion(const PlotRegion& region, PlotCoordinate::System newSystem) const { PlotCoordinate upperLeft = convertCoordinate(region.upperLeft(), newSystem); PlotCoordinate lowerRight = convertCoordinate(region.lowerRight(), newSystem); return PlotRegion(upperLeft, lowerRight); } vector<double> PlotCanvas::annotationWidthHeightDescent(const PlotAnnotationPtr annot) const { if(annot.null()) return vector<double>(); else return textWidthHeightDescent(annot->text(), annot->font()); } PlotMutexPtr PlotCanvas::mutex() const { PlotFactory* f = implementationFactory(); PlotMutexPtr m = f->mutex(); delete f; return m; } vector<vector<pair<unsigned int, unsigned int> > >* PlotCanvas::locate(const PlotRegion& r) const { PlotRegion region = convertRegion(r, PlotCoordinate::WORLD); vector<PlotPtr> plots = allPlots(); vector<vector<pair<unsigned int, unsigned int> > >* v = new vector<vector<pair<unsigned int, unsigned int> > >(plots.size()); if(plots.size() == 0) return v; PlotPointDataPtr data; double xLeft = region.upperLeft().x(), xRight = region.lowerRight().x(), yTop = region.upperLeft().y(), yBottom = region.lowerRight().y(); double x, y; vector<pair<unsigned int, unsigned int> >* v2; unsigned int rangeLow = 0; bool inRange; for(unsigned int i = 0; i < plots.size(); i++) { data = plots[i]->data(); if(data.null()) continue; // shouldn't happen v2 = &v->at(i); inRange = false; for(unsigned int j = 0; j < data->size(); j++) { x = data->xAt(j); y = data->yAt(j); if(x >= xLeft && x <= xRight && y <= yTop && y >= yBottom) { if(!inRange) { rangeLow = j; inRange = true; } } else if(inRange) { v2->push_back(pair<unsigned int, unsigned int>(rangeLow, j - 1)); inRange = false; } } // catch last range if(inRange) { v2->push_back(pair<unsigned int, unsigned int>(rangeLow, data->size() - 1)); } } return v; } void PlotCanvas::locateAndLog(const PlotRegion& region, PlotLoggerPtr logger) const { if(logger.null()) return; vector<vector<pair<unsigned int, unsigned int> > >* res = locate(region); PlotLogLocate msg("PlotCanvas", "locate", region, res); logger->postMessage(msg); } void PlotCanvas::registerMouseTool(PlotMouseToolPtr tool, bool activate, bool blocking) { if(tool.null()) return; tool->setActive(activate); tool->setBlocking(blocking); for(unsigned int i = 0; i < m_mouseTools.size(); i++) if(m_mouseTools[i] == tool) return; m_mouseTools.push_back(tool); tool->attach(this); } vector<PlotMouseToolPtr> PlotCanvas::allMouseTools() const { return m_mouseTools; } vector<PlotMouseToolPtr> PlotCanvas::activeMouseTools() const { vector<PlotMouseToolPtr> v; for(unsigned int i = 0; i < m_mouseTools.size(); i++) if(m_mouseTools[i]->isActive()) v.push_back(m_mouseTools[i]); return v; } void PlotCanvas::unregisterMouseTool(PlotMouseToolPtr tool) { if(tool.null()) return; for(unsigned int i = 0; i < m_mouseTools.size(); i++) { if(m_mouseTools[i] == tool) { m_mouseTools.erase(m_mouseTools.begin() + i); tool->detach(); return; } } } PlotStandardMouseToolGroupPtr PlotCanvas::standardMouseTools() { if(m_standardTools.null()) { PlotFactory* f = implementationFactory(); m_standardTools = f->standardMouseTools(); delete f; registerMouseTool(m_standardTools, false, true); } return m_standardTools; } // Macro for the handlers because they got very repetitive. #define PC_HANDLER1(TYPE,MEMBER) \ void PlotCanvas::register##TYPE##Handler(Plot##TYPE##EventHandlerPtr handler, \ PlotCoordinate::System system) { \ if(handler.null()) return; \ for(unsigned int i = 0; i < MEMBER .size(); i++) \ if( MEMBER [i].first == handler) return; \ MEMBER .push_back(pair<Plot##TYPE##EventHandlerPtr, \ PlotCoordinate::System>(handler, system)); \ } \ \ vector<Plot##TYPE##EventHandlerPtr> PlotCanvas::all##TYPE##Handlers() const { \ vector<Plot##TYPE##EventHandlerPtr> v( MEMBER .size()); \ for(unsigned int i = 0; i < v.size(); i++) v[i] = MEMBER [i].first; \ return v; \ } \ \ void PlotCanvas::unregister##TYPE##Handler(Plot##TYPE##EventHandlerPtr hndlr){\ for(unsigned int i = 0; i < MEMBER .size(); i++) { \ if( MEMBER [i].first == hndlr) { \ MEMBER .erase( MEMBER .begin() + i); \ break; \ } \ } \ } // Second macro which doesn't have the PlotCoordiate::System stuff. #define PC_HANDLER2(TYPE,MEMBER) \ void PlotCanvas::register##TYPE##Handler(Plot##TYPE##EventHandlerPtr handler){\ if(handler.null()) return; \ for(unsigned int i = 0; i < MEMBER .size(); i++) \ if( MEMBER [i] == handler) return; \ MEMBER .push_back(handler); \ } \ \ vector<Plot##TYPE##EventHandlerPtr> PlotCanvas::all##TYPE##Handlers() const { \ return MEMBER; } \ \ void PlotCanvas::unregister##TYPE##Handler(Plot##TYPE##EventHandlerPtr hndlr){\ for(unsigned int i = 0; i < MEMBER .size(); i++) { \ if( MEMBER [i] == hndlr) { \ MEMBER .erase( MEMBER .begin() + i); \ break; \ } \ } \ } PC_HANDLER1(Select, m_selectHandlers) PC_HANDLER1(Click, m_clickHandlers) PC_HANDLER1(MousePress, m_pressHandlers) PC_HANDLER1(MouseRelease, m_releaseHandlers) PC_HANDLER1(MouseDrag, m_dragHandlers) PC_HANDLER1(MouseMove, m_moveHandlers) PC_HANDLER1(Wheel, m_wheelHandlers) PC_HANDLER2(Key, m_keyHandlers) PC_HANDLER2(Resize, m_resizeHandlers) // Protected Methods // void PlotCanvas::resetMouseTools() { for(unsigned int i = 0; i < m_mouseTools.size(); i++) m_mouseTools[i]->reset(); } bool PlotCanvas::notifyDrawWatchers(PlotOperationPtr drawOperation, bool drawingIsThreaded, int drawnLayersFlag) { bool ret = true; for(unsigned int i = 0; i < m_drawWatchers.size(); i++) ret &= m_drawWatchers[i]->canvasDrawBeginning(drawOperation, drawingIsThreaded, drawnLayersFlag); return ret; } #define PC_EVENT_HELPER1(MEMBER) \ vector<PlotMouseToolPtr> active = activeMouseTools(); \ if( MEMBER .size() == 0 && active.size() == 0) return false; \ #define PC_SELECT_HELPER \ PlotRegion wreg = convertRegion(selectedRegion, PlotCoordinate::WORLD), \ nreg= convertRegion(selectedRegion, PlotCoordinate::NORMALIZED_WORLD),\ preg= convertRegion(selectedRegion, PlotCoordinate::PIXEL); \ PlotSelectEvent pe(this, preg), we(this, wreg), ne(this, nreg); #define PC_MOUSE_HELPER(EVENT) \ PlotCoordinate wc = convertCoordinate(coord, PlotCoordinate::WORLD), \ nc = convertCoordinate(coord, PlotCoordinate::NORMALIZED_WORLD), \ pc = convertCoordinate(wc, PlotCoordinate::PIXEL); \ EVENT we(this, button, wc), ne(this, button, nc), pe(this, button, pc); \ #define PC_WHEEL_HELPER \ PlotCoordinate wc = convertCoordinate(coord, PlotCoordinate::WORLD), \ nc = convertCoordinate(coord, PlotCoordinate::NORMALIZED_WORLD), \ pc = convertCoordinate(wc, PlotCoordinate::PIXEL); \ PlotWheelEvent we(this, delta, wc), ne(this, delta, nc), \ pe(this, delta, pc); #define PC_EVENT_HELPER2(MEMBER,TYPE) \ for(unsigned int i = 0; i < active.size(); i++) { \ switch(active[i]->getCoordinateSystem()) { \ case PlotCoordinate::WORLD: active[i]->handle##TYPE(we); break; \ case PlotCoordinate::PIXEL: active[i]->handle##TYPE(pe); break; \ case PlotCoordinate::NORMALIZED_WORLD: \ active[i]->handle##TYPE(ne); break; \ default: continue; \ } \ if(active[i]->isBlocking()&& active[i]->lastEventWasHandled()) \ return true; \ } \ \ for(unsigned int i = 0; i < MEMBER.size(); i++) { \ if(MEMBER[i].second == PlotCoordinate::WORLD) \ MEMBER[i].first->handle##TYPE(we); \ else if(MEMBER[i].second == PlotCoordinate::PIXEL) \ MEMBER[i].first->handle##TYPE(pe); \ else if(MEMBER[i].second == PlotCoordinate::NORMALIZED_WORLD) \ MEMBER[i].first->handle##TYPE(ne); \ } \ return true; #define PC_SELECT(MEMBER,TYPE) \ PC_EVENT_HELPER1(MEMBER) \ PC_SELECT_HELPER \ PC_EVENT_HELPER2(MEMBER,TYPE) #define PC_MOUSE(MEMBER,EVENT,TYPE) \ PC_EVENT_HELPER1(MEMBER) \ PC_MOUSE_HELPER(EVENT) \ PC_EVENT_HELPER2(MEMBER,TYPE) #define PC_WHEEL(MEMBER,TYPE) \ PC_EVENT_HELPER1(MEMBER) \ PC_WHEEL_HELPER \ PC_EVENT_HELPER2(MEMBER,TYPE) bool PlotCanvas::notifySelectHandlers(const PlotRegion& selectedRegion) { PC_SELECT(m_selectHandlers,Select) } bool PlotCanvas::notifyClickHandlers(PlotMouseEvent::Button button, const PlotCoordinate& coord) { PC_MOUSE(m_clickHandlers,PlotClickEvent,Click) } bool PlotCanvas::notifyPressHandlers(PlotMouseEvent::Button button, const PlotCoordinate& coord) { PC_MOUSE(m_pressHandlers,PlotMousePressEvent,MousePress) } bool PlotCanvas::notifyReleaseHandlers(PlotMouseEvent::Button button, const PlotCoordinate& coord) { PC_MOUSE(m_releaseHandlers,PlotMouseReleaseEvent,MouseRelease) } bool PlotCanvas::notifyDragHandlers(PlotMouseEvent::Button button, const PlotCoordinate& coord) { PC_MOUSE(m_dragHandlers,PlotMouseDragEvent,MouseDrag) } bool PlotCanvas::notifyMoveHandlers(PlotMouseEvent::Button button, const PlotCoordinate& coord) { PC_MOUSE(m_moveHandlers,PlotMouseMoveEvent,MouseMove) } bool PlotCanvas::notifyWheelHandlers(int delta, const PlotCoordinate& coord) { PC_WHEEL(m_wheelHandlers,Wheel) } #define PC_EVENT(MEMBER,EVENT,TYPE,...) \ if(MEMBER.size() == 0) return false; \ EVENT ev(this, __VA_ARGS__); \ for(unsigned int i = 0; i < MEMBER.size(); i++) \ MEMBER[i]->handle##TYPE(ev); \ return true; bool PlotCanvas::notifyKeyHandlers(char key, const vector<PlotKeyEvent::Modifier>& modifiers) { PC_EVENT(m_keyHandlers,PlotKeyEvent,Key,key,modifiers) } bool PlotCanvas::notifyResizeHandlers(int oldWidth, int oldHeight, int newWidth, int newHeight) { PC_EVENT(m_resizeHandlers,PlotResizeEvent,Resize,oldWidth,oldHeight, newWidth,newHeight) } }