From c10fce7d6aaa57a4f94f9d7aeea906597456f7ce Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 2 Dec 2009 19:27:07 +0100 Subject: Make the hover text conform to data displayed. Start of code to be more selective about the association between the hover text and the underling graph. Also, show the data set name in hover text. * grapher/GraphStyle.hxx (dataIndexAtPoint): New virtual function. * grapher/GraphStyle.cxx (dataIndexAtPoint): Implementation for bar graphs * grapher/GraphWidget.cxx (onHoverTimeout): Use dataIndexAtPoint. --- grapher/Graph.cxx | 18 ++++++++++-------- grapher/Graph.hxx | 2 ++ grapher/GraphData.hxx | 1 + grapher/GraphStyle.cxx | 26 ++++++++++++++++++++++++++ grapher/GraphStyle.hxx | 23 +++++++++++++++++------ grapher/GraphWidget.cxx | 27 +++++++++++++++------------ grapher/StapParser.cxx | 2 ++ 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/grapher/Graph.cxx b/grapher/Graph.cxx index 4b5b8eb6..55ffcdf2 100644 --- a/grapher/Graph.cxx +++ b/grapher/Graph.cxx @@ -13,7 +13,8 @@ namespace systemtap : _width(600), _height(200), _graphX(0), _graphY(0), _graphWidth(580), _graphHeight(180), _lineWidth(2), _autoScaling(true), _autoScrolling(true), - _zoomFactor(1.0), _playButton(new CairoPlayButton), + _zoomFactor(1.0), _xOffset(20.0), _yOffset(0.0), + _playButton(new CairoPlayButton), _left(0), _right(1), _top(5.0), _bottom(0.0) { setOrigin(x, y); @@ -80,7 +81,7 @@ namespace systemtap cr->save(); double horizScale = _zoomFactor * _graphWidth / static_cast(_right - _left); - cr->translate(20.0, 0.0); + cr->translate(_xOffset, _yOffset); cr->set_line_width(_lineWidth); for (DatasetList::iterator itr = _datasets.begin(), e = _datasets.end(); @@ -134,9 +135,9 @@ namespace systemtap cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL); cr->set_font_size(10.0); - cr->move_to(20.0, 0.0); - cr->line_to(20.0, _height); - cr->move_to(20.0, _graphHeight); + cr->move_to(_xOffset, _yOffset); + cr->line_to(_xOffset, _height); + cr->move_to(_xOffset, _graphHeight); cr->line_to(_graphWidth, _graphHeight); cr->stroke(); std::valarray dash(1); @@ -145,8 +146,8 @@ namespace systemtap double prevTextAdvance = 0; for (int64_t tickVal = startTime; tickVal <= _right; tickVal += majorUnit) { - double x = (tickVal - _left) * horizScale + 20.0; - cr->move_to(x, 0.0); + double x = (tickVal - _left) * horizScale + _xOffset; + cr->move_to(x, _yOffset); cr->line_to(x, _graphHeight); std::ostringstream stream; stream << tickVal; @@ -201,6 +202,7 @@ namespace systemtap int64_t Graph::getTimeAtPoint(double x) { - return _left + (_right - _left) * ((x - 20.0)/(_zoomFactor * _graphWidth)); + return (_left + + (_right - _left) * ((x - _xOffset)/(_zoomFactor * _graphWidth))); } } diff --git a/grapher/Graph.hxx b/grapher/Graph.hxx index e0e864d6..b9efb2a2 100644 --- a/grapher/Graph.hxx +++ b/grapher/Graph.hxx @@ -36,6 +36,8 @@ namespace systemtap bool _autoScaling; bool _autoScrolling; double _zoomFactor; + double _xOffset; + double _yOffset; std::tr1::shared_ptr _playButton; DatasetList& getDatasets() { return _datasets; } int64_t getTimeAtPoint(double x); diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx index 9a267fc5..04f415f3 100644 --- a/grapher/GraphData.hxx +++ b/grapher/GraphData.hxx @@ -27,6 +27,7 @@ namespace systemtap } virtual std::string elementAsString(size_t element) = 0; // size of grid square at "normal" viewing + std::string name; double scale; double color[3]; GraphStyle* style; diff --git a/grapher/GraphStyle.cxx b/grapher/GraphStyle.cxx index 887ed55f..55fc73f4 100644 --- a/grapher/GraphStyle.cxx +++ b/grapher/GraphStyle.cxx @@ -8,6 +8,9 @@ namespace systemtap using namespace std; using namespace tr1; + typedef pair TimeListPair; + GraphStyleBar GraphStyleBar::instance; void GraphStyleBar::draw(std::tr1::shared_ptr graphData, @@ -41,6 +44,29 @@ namespace systemtap } } + ssize_t GraphStyleBar::dataIndexAtPoint(double x, double y, + shared_ptr graphData, + shared_ptr graph) + { + shared_ptr > realData + = dynamic_pointer_cast >(graphData); + if (!realData) + return -1; + int64_t left, right; + double top, bottom; + graph->getExtents(left, right, top, bottom); + double t = graph->getTimeAtPoint(x); + TimeListPair range + = equal_range(graphData->times.begin(), graphData->times.end(), t); + size_t dataIndex = distance(graphData->times.begin(), range.first); + double val = realData->data[dataIndex]; + double ycoord = val * graph->_graphHeight / graphData->scale; + if (y >= graph->_yOffset + graph->_graphHeight - ycoord) + return static_cast(dataIndex); + else + return -1; + } + GraphStyleDot GraphStyleDot::instance; void GraphStyleDot::draw(std::tr1::shared_ptr graphData, diff --git a/grapher/GraphStyle.hxx b/grapher/GraphStyle.hxx index 4a0cd955..9625f451 100644 --- a/grapher/GraphStyle.hxx +++ b/grapher/GraphStyle.hxx @@ -14,29 +14,40 @@ namespace systemtap public: virtual void draw(std::tr1::shared_ptr graphData, Graph* graph, Cairo::RefPtr cr) = 0; + virtual ssize_t dataIndexAtPoint(double x, double y, + std::tr1::shared_ptr + graphData, + std::tr1::shared_ptr graph) + { + return -1; + } }; class GraphStyleBar : public GraphStyle { public: - virtual void draw(std::tr1::shared_ptr graphData, - Graph* graph, Cairo::RefPtr cr); + void draw(std::tr1::shared_ptr graphData, + Graph* graph, Cairo::RefPtr cr); + static GraphStyleBar instance; + ssize_t dataIndexAtPoint(double x, double y, + std::tr1::shared_ptr graphData, + std::tr1::shared_ptr graph); }; class GraphStyleDot : public GraphStyle { public: - virtual void draw(std::tr1::shared_ptr graphData, - Graph* graph, Cairo::RefPtr cr); + void draw(std::tr1::shared_ptr graphData, + Graph* graph, Cairo::RefPtr cr); static GraphStyleDot instance; }; class GraphStyleEvent : public GraphStyle { public: - virtual void draw(std::tr1::shared_ptr graphData, - Graph* graph, Cairo::RefPtr cr); + void draw(std::tr1::shared_ptr graphData, + Graph* graph, Cairo::RefPtr cr); static GraphStyleEvent instance; }; } diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx index 9a203d87..9067988a 100644 --- a/grapher/GraphWidget.cxx +++ b/grapher/GraphWidget.cxx @@ -276,20 +276,23 @@ namespace systemtap if (!_hoverText) _hoverText = shared_ptr(new CairoTextBox()); _hoverText->setOrigin(_mouseX + 5, _mouseY - 5); - int64_t t = g->getTimeAtPoint(_mouseX); Graph::DatasetList& dataSets = g->getDatasets(); - if (!dataSets.empty()) - { - shared_ptr gdbase = dataSets[0]; - GraphDataBase::TimeList::iterator itime - = std::lower_bound(gdbase->times.begin(), gdbase->times.end(), t); - if (itime != gdbase->times.end()) { - size_t index = distance(gdbase->times.begin(), itime); - _hoverText->contents = gdbase->elementAsString(index); - _hoverText->setVisible(true); - queue_draw(); + for (Graph::DatasetList::reverse_iterator ritr = dataSets.rbegin(), + end = dataSets.rend(); + ritr != end; + ++ritr) + { + ssize_t index + = (*ritr)->style->dataIndexAtPoint(_mouseX, _mouseY, *ritr, g); + if (index >= 0) + { + _hoverText->contents = (*ritr)->name + + ": " + (*ritr)->elementAsString(index); + _hoverText->setVisible(true); + queue_draw(); + break; } - } + } } return false; } diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index af5f2d7d..6218e229 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -101,6 +101,7 @@ vector commaSplit(const boost::sub_range& range) { std::tr1::shared_ptr > dataSet(new GraphData); + dataSet->name = setName; if (style == "dot") dataSet->style = &GraphStyleDot::instance; dataSet->color[0] = (hexColor >> 16) / 255.0; @@ -114,6 +115,7 @@ vector commaSplit(const boost::sub_range& range) { std::tr1::shared_ptr > dataSet(new GraphData); + dataSet->name = setName; dataSet->style = &GraphStyleEvent::instance; dataSet->color[0] = (hexColor >> 16) / 255.0; dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; -- cgit