diff options
-rw-r--r-- | grapher/CairoWidget.cxx | 162 | ||||
-rw-r--r-- | grapher/CairoWidget.hxx | 84 | ||||
-rw-r--r-- | grapher/Graph.cxx | 386 | ||||
-rw-r--r-- | grapher/Graph.hxx | 82 | ||||
-rw-r--r-- | grapher/GraphData.hxx | 104 | ||||
-rw-r--r-- | grapher/GraphStyle.cxx | 328 | ||||
-rw-r--r-- | grapher/GraphStyle.hxx | 84 | ||||
-rw-r--r-- | grapher/GraphWidget.cxx | 710 | ||||
-rw-r--r-- | grapher/GraphWidget.hxx | 150 | ||||
-rw-r--r-- | grapher/StapParser.cxx | 526 | ||||
-rw-r--r-- | grapher/StapParser.hxx | 112 |
11 files changed, 1364 insertions, 1364 deletions
diff --git a/grapher/CairoWidget.cxx b/grapher/CairoWidget.cxx index 26c2d029..81a6d3c7 100644 --- a/grapher/CairoWidget.cxx +++ b/grapher/CairoWidget.cxx @@ -15,89 +15,89 @@ namespace systemtap { - using namespace std; - using namespace boost; +using namespace std; +using namespace boost; - void CairoPlayButton::draw(Cairo::RefPtr<Cairo::Context> cr) - { - if (!_visible) - return; - cr->save(); - cr->set_line_width(1.0); - // square with rounded corners - cr->move_to(_x0, _y0 + _radius); - cr->arc(_x0 + _radius, _y0 + _radius, _radius, M_PI, -M_PI_2); - cr->line_to(_x0 + _size - _radius, _y0); - cr->arc(_x0 + _size - _radius, _y0 + _radius, _radius, -M_PI_2, 0.0); - cr->line_to(_x0 + _size, _y0 + _size - _radius); - cr->arc(_x0 + _size - _radius, _y0 + _size - _radius, _radius, 0.0, M_PI_2); - cr->line_to(_x0 + _radius, _y0 + _size); - cr->arc(_x0 + _radius, _y0 + _size - _radius, _radius, M_PI_2, M_PI); - cr->close_path(); - //cr->rectangle(_x0, _y0, 50.0, 50.0); - cr->set_source_rgba(1.0, 1.0, 1.0, .8); - cr->stroke(); - // play equalateral triangle - cr->move_to(_x0 + .25 * _size, _y0 + (.5 - 1.0 / (sqrt(3.0) * 2.0)) * _size); - cr->line_to(_x0 + .75 * _size, _y0 + .5 * _size); - cr->line_to(_x0 + .25 * _size, _y0 + (.5 + 1.0 / (sqrt(3.0) * 2.0)) * _size); - cr->close_path(); - cr->fill(); - cr->restore(); - } +void CairoPlayButton::draw(Cairo::RefPtr<Cairo::Context> cr) +{ + if (!_visible) + return; + cr->save(); + cr->set_line_width(1.0); + // square with rounded corners + cr->move_to(_x0, _y0 + _radius); + cr->arc(_x0 + _radius, _y0 + _radius, _radius, M_PI, -M_PI_2); + cr->line_to(_x0 + _size - _radius, _y0); + cr->arc(_x0 + _size - _radius, _y0 + _radius, _radius, -M_PI_2, 0.0); + cr->line_to(_x0 + _size, _y0 + _size - _radius); + cr->arc(_x0 + _size - _radius, _y0 + _size - _radius, _radius, 0.0, M_PI_2); + cr->line_to(_x0 + _radius, _y0 + _size); + cr->arc(_x0 + _radius, _y0 + _size - _radius, _radius, M_PI_2, M_PI); + cr->close_path(); + //cr->rectangle(_x0, _y0, 50.0, 50.0); + cr->set_source_rgba(1.0, 1.0, 1.0, .8); + cr->stroke(); + // play equalateral triangle + cr->move_to(_x0 + .25 * _size, _y0 + (.5 - 1.0 / (sqrt(3.0) * 2.0)) * _size); + cr->line_to(_x0 + .75 * _size, _y0 + .5 * _size); + cr->line_to(_x0 + .25 * _size, _y0 + (.5 + 1.0 / (sqrt(3.0) * 2.0)) * _size); + cr->close_path(); + cr->fill(); + cr->restore(); +} - bool CairoPlayButton::containsPoint(double x, double y) - { - if (x >= _x0 && (x < (_x0 + 50.0)) && (y >= _y0) && (y < (_y0 + 50))) - return true; - else +bool CairoPlayButton::containsPoint(double x, double y) +{ + if (x >= _x0 && (x < (_x0 + 50.0)) && (y >= _y0) && (y < (_y0 + 50))) + return true; + else return false; - } +} - void CairoTextBox::draw(Cairo::RefPtr<Cairo::Context> cr) - { - if (!_visible) - return; - cr->save(); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_BOLD); - cr->set_font_size(10.0); - Cairo::FontExtents fontExtent; - cr->get_font_extents(fontExtent); - // Some naughty fonts have a height less than ascent + descent - double fontHeight = max(fontExtent.ascent + fontExtent.descent + 1.0, - fontExtent.height); - vector<string> lines; - split(lines, contents, is_any_of("\n")); - vector<Cairo::TextExtents> extents; - double width = 0.0, height = 0.0; - for (vector<string>::iterator itr = lines.begin(), end = lines.end(); - itr != end; - ++itr) - { - Cairo::TextExtents extent; - cr->get_text_extents(*itr, extent); - extents.push_back(extent); - width = max(width, extent.width); - height += fontHeight; - } - cr->move_to(_x0 - 2, _y0 - 2); - cr->line_to(_x0 + width + 2, _y0 - 2); - cr->line_to(_x0 + width + 2, _y0 + height + 2); - cr->line_to(_x0 - 2, _y0 + height + 2); - cr->close_path(); - cr->set_source_rgba(1.0, 1.0, 1.0, .8); - cr->fill(); - cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); - double texty = _y0; - for (vector<string>::iterator itr = lines.begin(), end = lines.end(); - itr != end; - ++itr) - { - cr->move_to(_x0, texty + fontExtent.ascent); - cr->show_text(*itr); - texty += fontHeight; - } - cr->restore(); - } +void CairoTextBox::draw(Cairo::RefPtr<Cairo::Context> cr) +{ + if (!_visible) + return; + cr->save(); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_BOLD); + cr->set_font_size(10.0); + Cairo::FontExtents fontExtent; + cr->get_font_extents(fontExtent); + // Some naughty fonts have a height less than ascent + descent + double fontHeight = max(fontExtent.ascent + fontExtent.descent + 1.0, + fontExtent.height); + vector<string> lines; + split(lines, contents, is_any_of("\n")); + vector<Cairo::TextExtents> extents; + double width = 0.0, height = 0.0; + for (vector<string>::iterator itr = lines.begin(), end = lines.end(); + itr != end; + ++itr) + { + Cairo::TextExtents extent; + cr->get_text_extents(*itr, extent); + extents.push_back(extent); + width = max(width, extent.width); + height += fontHeight; + } + cr->move_to(_x0 - 2, _y0 - 2); + cr->line_to(_x0 + width + 2, _y0 - 2); + cr->line_to(_x0 + width + 2, _y0 + height + 2); + cr->line_to(_x0 - 2, _y0 + height + 2); + cr->close_path(); + cr->set_source_rgba(1.0, 1.0, 1.0, .8); + cr->fill(); + cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); + double texty = _y0; + for (vector<string>::iterator itr = lines.begin(), end = lines.end(); + itr != end; + ++itr) + { + cr->move_to(_x0, texty + fontExtent.ascent); + cr->show_text(*itr); + texty += fontHeight; + } + cr->restore(); +} } diff --git a/grapher/CairoWidget.hxx b/grapher/CairoWidget.hxx index bcabafb2..32d92cce 100644 --- a/grapher/CairoWidget.hxx +++ b/grapher/CairoWidget.hxx @@ -12,51 +12,51 @@ #include <cairomm/context.h> namespace systemtap { - class CairoWidget +class CairoWidget +{ +public: + CairoWidget(bool visible = false) + : _visible(visible) + {} + bool isVisible() const { return _visible; } + void setVisible(bool visible) { _visible = visible; } + void getOrigin(double &x, double &y) const { - public: - CairoWidget(bool visible = false) - : _visible(visible) - {} - bool isVisible() const { return _visible; } - void setVisible(bool visible) { _visible = visible; } - void getOrigin(double &x, double &y) const - { - x = _x0; - y = _y0; - } - void setOrigin(double x, double y) - { - _x0 = x; - _y0 = y; - } - virtual void draw(Cairo::RefPtr<Cairo::Context> cr) = 0; - virtual bool containsPoint(double x, double y) { return false; } - protected: - bool _visible; - double _x0; - double _y0; - }; - - class CairoPlayButton : public CairoWidget + x = _x0; + y = _y0; + } + void setOrigin(double x, double y) { - public: - CairoPlayButton(bool visible = false) - : CairoWidget(visible), _size(50.0), _radius(5) - { - } - virtual void draw(Cairo::RefPtr<Cairo::Context> cr); - virtual bool containsPoint(double x, double y); - protected: - double _size; - double _radius; - }; + _x0 = x; + _y0 = y; + } + virtual void draw(Cairo::RefPtr<Cairo::Context> cr) = 0; + virtual bool containsPoint(double x, double y) { return false; } +protected: + bool _visible; + double _x0; + double _y0; +}; - class CairoTextBox : public CairoWidget +class CairoPlayButton : public CairoWidget +{ +public: + CairoPlayButton(bool visible = false) + : CairoWidget(visible), _size(50.0), _radius(5) { - public: - void draw(Cairo::RefPtr<Cairo::Context> cr); - std::string contents; - }; + } + virtual void draw(Cairo::RefPtr<Cairo::Context> cr); + virtual bool containsPoint(double x, double y); +protected: + double _size; + double _radius; +}; + +class CairoTextBox : public CairoWidget +{ +public: + void draw(Cairo::RefPtr<Cairo::Context> cr); + std::string contents; +}; } #endif diff --git a/grapher/Graph.cxx b/grapher/Graph.cxx index ea1bd091..dc808fa4 100644 --- a/grapher/Graph.cxx +++ b/grapher/Graph.cxx @@ -14,213 +14,213 @@ namespace systemtap { - using namespace std; - using namespace std::tr1; +using namespace std; +using namespace std::tr1; - GraphDataList GraphDataBase::graphData; - sigc::signal<void> GraphDataBase::graphDataChanged; +GraphDataList GraphDataBase::graphData; +sigc::signal<void> GraphDataBase::graphDataChanged; - Graph::Graph(double x, double y) - : _width(600), _height(200), _graphX(0), _graphY(0), - _graphWidth(580), _graphHeight(180), - _lineWidth(2), _autoScaling(true), _autoScrolling(true), - _zoomFactor(1.0), _xOffset(20.0), _yOffset(0.0), - _playButton(new CairoPlayButton), _timeBase(0), - _left(0), _right(1), _top(5.0), _bottom(0.0) - { - setOrigin(x, y); - _graphX = x; - _graphY = y; - } +Graph::Graph(double x, double y) + : _width(600), _height(200), _graphX(0), _graphY(0), + _graphWidth(580), _graphHeight(180), + _lineWidth(2), _autoScaling(true), _autoScrolling(true), + _zoomFactor(1.0), _xOffset(20.0), _yOffset(0.0), + _playButton(new CairoPlayButton), _timeBase(0), + _left(0), _right(1), _top(5.0), _bottom(0.0) +{ + setOrigin(x, y); + _graphX = x; + _graphY = y; +} - void Graph::draw(Cairo::RefPtr<Cairo::Context> cr) - { +void Graph::draw(Cairo::RefPtr<Cairo::Context> cr) +{ - if (_autoScaling) - { - // line separation - int linesPossible = (int)(_graphWidth / (_lineWidth + 2.0)); - // Find latest time. - int64_t latestTime = 0; - for (GraphDataList::iterator ditr = _datasets.begin(), - de = _datasets.end(); - ditr != de; - ++ditr) - { - if (!(*ditr)->times.empty()) - { - int64_t lastDataTime = (*ditr)->times.back(); - if (lastDataTime > latestTime) - latestTime = lastDataTime; - } - } - int64_t minDiff = 0; - int64_t maxTotal = 0; - for (GraphDataList::iterator ditr = _datasets.begin(), - de = _datasets.end(); - ditr != de; - ++ditr) - { - GraphDataBase::TimeList& gtimes = (*ditr)->times; - if (gtimes.size() <= 1) - continue; - double totalDiff = 0.0; - for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(), - re = gtimes.rend(); - ritr + 1 != gtimes.rend(); - ritr++) - { - int64_t timeDiff = *ritr - *(ritr + 1); - if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0)) - minDiff = timeDiff; - if (minDiff != 0 - && ((totalDiff + timeDiff) / minDiff + 1) > linesPossible) - break; - totalDiff += timeDiff; - } - if (totalDiff > maxTotal) - maxTotal = totalDiff; - } - // Now we have a global scale. - _right = latestTime; - if (maxTotal != 0) - _left = latestTime - maxTotal; - else - _left = _right - 1; - } - cr->save(); - double horizScale - = _zoomFactor * _graphWidth / static_cast<double>(_right - _left); - cr->translate(_xOffset, _yOffset); - cr->set_line_width(_lineWidth); + if (_autoScaling) + { + // line separation + int linesPossible = (int)(_graphWidth / (_lineWidth + 2.0)); + // Find latest time. + int64_t latestTime = 0; + for (GraphDataList::iterator ditr = _datasets.begin(), + de = _datasets.end(); + ditr != de; + ++ditr) + { + if (!(*ditr)->times.empty()) + { + int64_t lastDataTime = (*ditr)->times.back(); + if (lastDataTime > latestTime) + latestTime = lastDataTime; + } + } + int64_t minDiff = 0; + int64_t maxTotal = 0; + for (GraphDataList::iterator ditr = _datasets.begin(), + de = _datasets.end(); + ditr != de; + ++ditr) + { + GraphDataBase::TimeList& gtimes = (*ditr)->times; + if (gtimes.size() <= 1) + continue; + double totalDiff = 0.0; + for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(), + re = gtimes.rend(); + ritr + 1 != gtimes.rend(); + ritr++) + { + int64_t timeDiff = *ritr - *(ritr + 1); + if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0)) + minDiff = timeDiff; + if (minDiff != 0 + && ((totalDiff + timeDiff) / minDiff + 1) > linesPossible) + break; + totalDiff += timeDiff; + } + if (totalDiff > maxTotal) + maxTotal = totalDiff; + } + // Now we have a global scale. + _right = latestTime; + if (maxTotal != 0) + _left = latestTime - maxTotal; + else + _left = _right - 1; + } + cr->save(); + double horizScale + = _zoomFactor * _graphWidth / static_cast<double>(_right - _left); + cr->translate(_xOffset, _yOffset); + cr->set_line_width(_lineWidth); - for (GraphDataList::iterator itr = _datasets.begin(), e = _datasets.end(); - itr != e; - ++itr) - { - shared_ptr<GraphDataBase> graphData = *itr; - cr->save(); - cr->translate(0.0, _graphHeight); - cr->scale(1.0, -1.0); - graphData->style->draw(graphData, this, cr); - cr->restore(); - cr->save(); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_BOLD); - cr->set_font_size(14.0); - cr->set_source_rgba(1.0, 1.0, 1.0, .8); + for (GraphDataList::iterator itr = _datasets.begin(), e = _datasets.end(); + itr != e; + ++itr) + { + shared_ptr<GraphDataBase> graphData = *itr; + cr->save(); + cr->translate(0.0, _graphHeight); + cr->scale(1.0, -1.0); + graphData->style->draw(graphData, this, cr); + cr->restore(); + cr->save(); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_BOLD); + cr->set_font_size(14.0); + cr->set_source_rgba(1.0, 1.0, 1.0, .8); - if (!graphData->title.empty()) - { - cr->move_to(20.0, 20.0); - cr->show_text(graphData->title); - } - if (!graphData->xAxisText.empty()) - { - cr->move_to(10.0, _graphHeight - 5); - cr->show_text(graphData->xAxisText); - } - if (!graphData->yAxisText.empty()) - { - cr->save(); - cr->translate(10.0, _height - 10.0); - cr->rotate(-M_PI / 2.0); - cr->move_to(10.0, 0.0); - cr->show_text(graphData->yAxisText); - cr->restore(); - } - cr->restore(); + if (!graphData->title.empty()) + { + cr->move_to(20.0, 20.0); + cr->show_text(graphData->title); + } + if (!graphData->xAxisText.empty()) + { + cr->move_to(10.0, _graphHeight - 5); + cr->show_text(graphData->xAxisText); + } + if (!graphData->yAxisText.empty()) + { + cr->save(); + cr->translate(10.0, _height - 10.0); + cr->rotate(-M_PI / 2.0); + cr->move_to(10.0, 0.0); + cr->show_text(graphData->yAxisText); + cr->restore(); + } + cr->restore(); - } - cr->restore(); - // Draw axes - double diff = static_cast<double>(_right - _left); - int64_t majorUnit - = static_cast<int64_t>(pow(10.0, floor(log(diff) / log(10.0)))); - int64_t startTime = (_left / majorUnit) * majorUnit; - cr->save(); - cr->set_source_rgba(1.0, 1.0, 1.0, .9); - cr->set_line_cap(Cairo::LINE_CAP_BUTT); - cr->set_line_width(_lineWidth); - cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, - Cairo::FONT_WEIGHT_NORMAL); - cr->set_font_size(10.0); - cr->move_to(_xOffset, _yOffset); - cr->line_to(_xOffset, _height); - cr->move_to(_xOffset, _graphHeight); - cr->line_to(_graphWidth, _graphHeight); - cr->stroke(); - std::valarray<double> dash(1); - dash[0] = _graphHeight / 10; - cr->set_dash(dash, 0); - double prevTextAdvance = 0; - for (int64_t tickVal = startTime; tickVal <= _right; tickVal += majorUnit) - { - double x = (tickVal - _left) * horizScale + _xOffset; - cr->move_to(x, _yOffset); - cr->line_to(x, _graphHeight); - std::ostringstream stream; - stream << (tickVal - _timeBase); - Cairo::TextExtents extents; - cr->get_text_extents(stream.str(), extents); - // Room for this label? - if (x + extents.x_bearing > prevTextAdvance) - { - cr->move_to(x, _graphHeight + 5 + extents.height); - cr->show_text(stream.str()); - prevTextAdvance = x + extents.x_advance; - } - } - cr->stroke(); - cr->restore(); + } + cr->restore(); + // Draw axes + double diff = static_cast<double>(_right - _left); + int64_t majorUnit + = static_cast<int64_t>(pow(10.0, floor(log(diff) / log(10.0)))); + int64_t startTime = (_left / majorUnit) * majorUnit; + cr->save(); + cr->set_source_rgba(1.0, 1.0, 1.0, .9); + cr->set_line_cap(Cairo::LINE_CAP_BUTT); + cr->set_line_width(_lineWidth); + cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, + Cairo::FONT_WEIGHT_NORMAL); + cr->set_font_size(10.0); + cr->move_to(_xOffset, _yOffset); + cr->line_to(_xOffset, _height); + cr->move_to(_xOffset, _graphHeight); + cr->line_to(_graphWidth, _graphHeight); + cr->stroke(); + std::valarray<double> dash(1); + dash[0] = _graphHeight / 10; + cr->set_dash(dash, 0); + double prevTextAdvance = 0; + for (int64_t tickVal = startTime; tickVal <= _right; tickVal += majorUnit) + { + double x = (tickVal - _left) * horizScale + _xOffset; + cr->move_to(x, _yOffset); + cr->line_to(x, _graphHeight); + std::ostringstream stream; + stream << (tickVal - _timeBase); + Cairo::TextExtents extents; + cr->get_text_extents(stream.str(), extents); + // Room for this label? + if (x + extents.x_bearing > prevTextAdvance) + { + cr->move_to(x, _graphHeight + 5 + extents.height); + cr->show_text(stream.str()); + prevTextAdvance = x + extents.x_advance; + } + } + cr->stroke(); + cr->restore(); - if (!_autoScrolling) - { - _playButton->setVisible(true); - _playButton->setOrigin(_graphWidth / 2 - 25, .875 * _graphHeight - 50); - _playButton->draw(cr); - } + if (!_autoScrolling) + { + _playButton->setVisible(true); + _playButton->setOrigin(_graphWidth / 2 - 25, .875 * _graphHeight - 50); + _playButton->draw(cr); + } - } +} - void Graph::addGraphData(shared_ptr<GraphDataBase> data) - { - _datasets.push_back(data); - } +void Graph::addGraphData(shared_ptr<GraphDataBase> data) +{ + _datasets.push_back(data); +} - void Graph::getExtents(int64_t& left, int64_t& right, double& top, - double& bottom) const - { - left = _left; - right = _right; - top = _top; - bottom = _bottom; - } +void Graph::getExtents(int64_t& left, int64_t& right, double& top, + double& bottom) const +{ + left = _left; + right = _right; + top = _top; + bottom = _bottom; +} - void Graph::setExtents(int64_t left, int64_t right, double top, double bottom) - { - _left = left; - _right = right; - _top = top; - _bottom = bottom; - } +void Graph::setExtents(int64_t left, int64_t right, double top, double bottom) +{ + _left = left; + _right = right; + _top = top; + _bottom = bottom; +} - bool Graph::containsPoint(double x, double y) - { - return x >= _x0 && x < _x0 + _width && y >= _y0 && y < _y0 + _height; - } +bool Graph::containsPoint(double x, double y) +{ + return x >= _x0 && x < _x0 + _width && y >= _y0 && y < _y0 + _height; +} - int64_t Graph::getTimeAtPoint(double x) - { - return (_left - + (_right - _left) * ((x - _xOffset)/(_zoomFactor * _graphWidth))); - } +int64_t Graph::getTimeAtPoint(double x) +{ + return (_left + + (_right - _left) * ((x - _xOffset)/(_zoomFactor * _graphWidth))); +} - void Graph::window2GraphCoords(double x, double y, - double& xgraph, double& ygraph) - { - xgraph = x -_xOffset; - ygraph = -(y - _graphY) + _yOffset + _graphHeight; - } +void Graph::window2GraphCoords(double x, double y, + double& xgraph, double& ygraph) +{ + xgraph = x -_xOffset; + ygraph = -(y - _graphY) + _yOffset + _graphHeight; +} } diff --git a/grapher/Graph.hxx b/grapher/Graph.hxx index c928fec2..efabd22d 100644 --- a/grapher/Graph.hxx +++ b/grapher/Graph.hxx @@ -16,46 +16,46 @@ namespace systemtap { - class Graph : public CairoWidget - { - public: - friend class GraphWidget; - Graph(double x = 0.0, double y = 0.0); - virtual void draw(Cairo::RefPtr<Cairo::Context> cr); - virtual bool containsPoint(double x, double y); - double getLineWidth() { return _lineWidth; } - void setLineWidth(double lineWidth) { _lineWidth = lineWidth; } - bool getAutoScaling() const { return _autoScaling; } - void setAutoScaling(bool val) { _autoScaling = val; } - void addGraphData(std::tr1::shared_ptr<GraphDataBase> data); - void getExtents(int64_t& left, int64_t& right, double& top, double& bottom) - const; - void setExtents(int64_t left, int64_t right, double top, double bottom); - // extents of the whole graph area - double _width; - double _height; - // Position, extents of the graph - double _graphX; - double _graphY; - double _graphWidth; - double _graphHeight; - double _lineWidth; - bool _autoScaling; - bool _autoScrolling; - double _zoomFactor; - double _xOffset; - double _yOffset; - std::tr1::shared_ptr<CairoPlayButton> _playButton; - int64_t _timeBase; - GraphDataList& getDatasets() { return _datasets; } - int64_t getTimeAtPoint(double x); - void window2GraphCoords(double x, double y, double& xgraph, double& ygraph); - protected: - GraphDataList _datasets; - int64_t _left; - int64_t _right; - double _top; - double _bottom; - }; +class Graph : public CairoWidget +{ +public: + friend class GraphWidget; + Graph(double x = 0.0, double y = 0.0); + virtual void draw(Cairo::RefPtr<Cairo::Context> cr); + virtual bool containsPoint(double x, double y); + double getLineWidth() { return _lineWidth; } + void setLineWidth(double lineWidth) { _lineWidth = lineWidth; } + bool getAutoScaling() const { return _autoScaling; } + void setAutoScaling(bool val) { _autoScaling = val; } + void addGraphData(std::tr1::shared_ptr<GraphDataBase> data); + void getExtents(int64_t& left, int64_t& right, double& top, double& bottom) + const; + void setExtents(int64_t left, int64_t right, double top, double bottom); + // extents of the whole graph area + double _width; + double _height; + // Position, extents of the graph + double _graphX; + double _graphY; + double _graphWidth; + double _graphHeight; + double _lineWidth; + bool _autoScaling; + bool _autoScrolling; + double _zoomFactor; + double _xOffset; + double _yOffset; + std::tr1::shared_ptr<CairoPlayButton> _playButton; + int64_t _timeBase; + GraphDataList& getDatasets() { return _datasets; } + int64_t getTimeAtPoint(double x); + void window2GraphCoords(double x, double y, double& xgraph, double& ygraph); +protected: + GraphDataList _datasets; + int64_t _left; + int64_t _right; + double _top; + double _bottom; +}; } #endif diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx index fb1ca9f5..863b1d07 100644 --- a/grapher/GraphData.hxx +++ b/grapher/GraphData.hxx @@ -25,63 +25,63 @@ namespace systemtap { - struct GraphDataBase; - typedef std::vector<std::tr1::shared_ptr<GraphDataBase> > GraphDataList; - struct GraphDataBase - { - virtual ~GraphDataBase() {} +struct GraphDataBase; +typedef std::vector<std::tr1::shared_ptr<GraphDataBase> > GraphDataList; +struct GraphDataBase +{ + virtual ~GraphDataBase() {} - typedef boost::circular_buffer<int64_t> TimeList; - GraphDataBase(TimeList::capacity_type cap = 50000) - : scale(1.0), style(&GraphStyleBar::instance), times(cap) - { - color[0] = 0.0; color[1] = 1.0; color[2] = 0.0; - } - 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; - std::string title; - std::string xAxisText; - std::string yAxisText; - TimeList times; - static GraphDataList graphData; - // signal stuff for telling everyone about changes to the data set list - static sigc::signal<void> graphDataChanged; - }; + typedef boost::circular_buffer<int64_t> TimeList; + GraphDataBase(TimeList::capacity_type cap = 50000) + : scale(1.0), style(&GraphStyleBar::instance), times(cap) + { + color[0] = 0.0; color[1] = 1.0; color[2] = 0.0; + } + 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; + std::string title; + std::string xAxisText; + std::string yAxisText; + TimeList times; + static GraphDataList graphData; + // signal stuff for telling everyone about changes to the data set list + static sigc::signal<void> graphDataChanged; +}; - template<typename T> - class GraphData : public GraphDataBase +template<typename T> +class GraphData : public GraphDataBase +{ +public: + typedef T data_type; + typedef boost::circular_buffer<data_type> DataList; + GraphData(typename DataList::capacity_type cap = 50000) + : GraphDataBase(cap), data(cap) { - public: - typedef T data_type; - typedef boost::circular_buffer<data_type> DataList; - GraphData(typename DataList::capacity_type cap = 50000) - : GraphDataBase(cap), data(cap) - { - } - std::string elementAsString(size_t element) - { - std::ostringstream stream; - stream << data[element]; - return stream.str(); - } - DataList data; - }; - struct CSVData + } + std::string elementAsString(size_t element) { - typedef std::pair<std::string, std::tr1::shared_ptr<GraphDataBase> > - Element; - std::vector<Element> elements; - }; + std::ostringstream stream; + stream << data[element]; + return stream.str(); + } + DataList data; +}; +struct CSVData +{ + typedef std::pair<std::string, std::tr1::shared_ptr<GraphDataBase> > + Element; + std::vector<Element> elements; +}; - inline GraphDataList& getGraphData() { return GraphDataBase::graphData; } +inline GraphDataList& getGraphData() { return GraphDataBase::graphData; } - inline sigc::signal<void>& graphDataSignal() - { - return GraphDataBase::graphDataChanged; - } +inline sigc::signal<void>& graphDataSignal() +{ + return GraphDataBase::graphDataChanged; +} } #endif diff --git a/grapher/GraphStyle.cxx b/grapher/GraphStyle.cxx index 69ff4089..6bf4e109 100644 --- a/grapher/GraphStyle.cxx +++ b/grapher/GraphStyle.cxx @@ -13,179 +13,179 @@ namespace systemtap { - using namespace std; - using namespace tr1; +using namespace std; +using namespace tr1; - typedef pair<GraphDataBase::TimeList::iterator, - GraphDataBase::TimeList::iterator> TimeListPair; +typedef pair<GraphDataBase::TimeList::iterator, + GraphDataBase::TimeList::iterator> TimeListPair; - GraphStyleBar GraphStyleBar::instance; +GraphStyleBar GraphStyleBar::instance; - void GraphStyleBar::draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr) - { - shared_ptr<GraphData<double> > realData - = dynamic_pointer_cast<GraphData<double> >(graphData); - if (!realData) - return; - int64_t left, right; - double top, bottom; - graph->getExtents(left, right, top, bottom); - double horizScale = (graph->_zoomFactor * graph->_graphWidth - / static_cast<double>(right - left)); - GraphDataBase::TimeList::iterator lower - = lower_bound(graphData->times.begin(), graphData->times.end(), left); - GraphDataBase::TimeList::iterator upper - = upper_bound(graphData->times.begin(), graphData->times.end(), right); - for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; - ditr != de; - ++ditr) - { - size_t dataIndex = ditr - graphData->times.begin(); - cr->set_source_rgba(graphData->color[0], graphData->color[1], - graphData->color[2], 1.0); - cr->move_to((*ditr - left) * horizScale, 0); - cr->line_to((*ditr - left) * horizScale, - realData->data[dataIndex] * graph->_graphHeight - / graphData->scale); - cr->stroke(); - } - } +void GraphStyleBar::draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr) +{ + shared_ptr<GraphData<double> > realData + = dynamic_pointer_cast<GraphData<double> >(graphData); + if (!realData) + return; + int64_t left, right; + double top, bottom; + graph->getExtents(left, right, top, bottom); + double horizScale = (graph->_zoomFactor * graph->_graphWidth + / static_cast<double>(right - left)); + GraphDataBase::TimeList::iterator lower + = lower_bound(graphData->times.begin(), graphData->times.end(), left); + GraphDataBase::TimeList::iterator upper + = upper_bound(graphData->times.begin(), graphData->times.end(), right); + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; + ditr != de; + ++ditr) + { + size_t dataIndex = ditr - graphData->times.begin(); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], 1.0); + cr->move_to((*ditr - left) * horizScale, 0); + cr->line_to((*ditr - left) * horizScale, + realData->data[dataIndex] * graph->_graphHeight + / graphData->scale); + cr->stroke(); + } +} - ssize_t GraphStyleBar::dataIndexAtPoint(double x, double y, - shared_ptr<GraphDataBase> graphData, - shared_ptr<Graph> graph) - { - shared_ptr<GraphData<double> > realData - = dynamic_pointer_cast<GraphData<double> >(graphData); - if (!realData || graphData->times.empty()) - 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); - if (range.first == graphData->times.end()) - return -1; - 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<ssize_t>(dataIndex); - else - return -1; - } +ssize_t GraphStyleBar::dataIndexAtPoint(double x, double y, + shared_ptr<GraphDataBase> graphData, + shared_ptr<Graph> graph) +{ + shared_ptr<GraphData<double> > realData + = dynamic_pointer_cast<GraphData<double> >(graphData); + if (!realData || graphData->times.empty()) + 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); + if (range.first == graphData->times.end()) + return -1; + 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<ssize_t>(dataIndex); + else + return -1; +} - GraphStyleDot GraphStyleDot::instance; +GraphStyleDot GraphStyleDot::instance; - void GraphStyleDot::draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr) - { - shared_ptr<GraphData<double> > realData - = dynamic_pointer_cast<GraphData<double> >(graphData); - if (!realData) - return; - int64_t left, right; - double top, bottom; - graph->getExtents(left, right, top, bottom); - double horizScale = (graph->_zoomFactor * graph->_graphWidth - / static_cast<double>(right - left)); - GraphDataBase::TimeList::iterator lower - = lower_bound(graphData->times.begin(), graphData->times.end(), left); - GraphDataBase::TimeList::iterator upper - = upper_bound(graphData->times.begin(), graphData->times.end(), right); - cr->set_source_rgba(graphData->color[0], graphData->color[1], - graphData->color[2], 1.0); +void GraphStyleDot::draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr) +{ + shared_ptr<GraphData<double> > realData + = dynamic_pointer_cast<GraphData<double> >(graphData); + if (!realData) + return; + int64_t left, right; + double top, bottom; + graph->getExtents(left, right, top, bottom); + double horizScale = (graph->_zoomFactor * graph->_graphWidth + / static_cast<double>(right - left)); + GraphDataBase::TimeList::iterator lower + = lower_bound(graphData->times.begin(), graphData->times.end(), left); + GraphDataBase::TimeList::iterator upper + = upper_bound(graphData->times.begin(), graphData->times.end(), right); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], 1.0); - for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; - ditr != de; - ++ditr) - { - size_t dataIndex = ditr - graphData->times.begin(); - cr->arc((*ditr - left) * horizScale, - (realData->data[dataIndex] - * graph->_graphHeight / graphData->scale), - graph->_lineWidth / 2.0, 0.0, M_PI * 2.0); - cr->fill(); - } - } + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; + ditr != de; + ++ditr) + { + size_t dataIndex = ditr - graphData->times.begin(); + cr->arc((*ditr - left) * horizScale, + (realData->data[dataIndex] + * graph->_graphHeight / graphData->scale), + graph->_lineWidth / 2.0, 0.0, M_PI * 2.0); + cr->fill(); + } +} - GraphStyleEvent GraphStyleEvent::instance; +GraphStyleEvent GraphStyleEvent::instance; - void GraphStyleEvent::draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr) - { - shared_ptr<GraphData<string> > stringData - = dynamic_pointer_cast<GraphData<string> >(graphData); - if (!stringData) - return; - int64_t left, right; - double top, bottom; - graph->getExtents(left, right, top, bottom); - double horizScale = (graph->_zoomFactor * graph->_graphWidth - / static_cast<double>(right - left)); - double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); - cr->save(); - cr->set_line_width(3 * graph->_lineWidth); - cr->set_source_rgba(graphData->color[0], graphData->color[1], - graphData->color[2], .33); - cr->move_to(0, eventHeight); - cr->line_to(graph->_graphWidth, eventHeight); - cr->stroke(); - cr->restore(); - GraphDataBase::TimeList::iterator lower - = lower_bound(graphData->times.begin(), graphData->times.end(), left); - GraphDataBase::TimeList::iterator upper - = upper_bound(graphData->times.begin(), graphData->times.end(), right); - for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; - ditr != de; - ++ditr) - { - // size_t dataIndex = ditr - graphData->times.begin(); - double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); - cr->save(); - cr->set_source_rgba(graphData->color[0], graphData->color[1], - graphData->color[2], 1.0); - cr->rectangle((*ditr - left) * horizScale - 1.5 * graph->_lineWidth, - eventHeight - 1.5 * graph->_lineWidth, - 3.0 * graph->_lineWidth, 3.0 * graph->_lineWidth); - cr->fill(); - cr->restore(); - } - } +void GraphStyleEvent::draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr) +{ + shared_ptr<GraphData<string> > stringData + = dynamic_pointer_cast<GraphData<string> >(graphData); + if (!stringData) + return; + int64_t left, right; + double top, bottom; + graph->getExtents(left, right, top, bottom); + double horizScale = (graph->_zoomFactor * graph->_graphWidth + / static_cast<double>(right - left)); + double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); + cr->save(); + cr->set_line_width(3 * graph->_lineWidth); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], .33); + cr->move_to(0, eventHeight); + cr->line_to(graph->_graphWidth, eventHeight); + cr->stroke(); + cr->restore(); + GraphDataBase::TimeList::iterator lower + = lower_bound(graphData->times.begin(), graphData->times.end(), left); + GraphDataBase::TimeList::iterator upper + = upper_bound(graphData->times.begin(), graphData->times.end(), right); + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; + ditr != de; + ++ditr) + { + // size_t dataIndex = ditr - graphData->times.begin(); + double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); + cr->save(); + cr->set_source_rgba(graphData->color[0], graphData->color[1], + graphData->color[2], 1.0); + cr->rectangle((*ditr - left) * horizScale - 1.5 * graph->_lineWidth, + eventHeight - 1.5 * graph->_lineWidth, + 3.0 * graph->_lineWidth, 3.0 * graph->_lineWidth); + cr->fill(); + cr->restore(); + } +} - ssize_t GraphStyleEvent::dataIndexAtPoint(double x, double y, - shared_ptr<GraphDataBase> graphData, - shared_ptr<Graph> graph) - { - shared_ptr<GraphData<string> > stringData - = dynamic_pointer_cast<GraphData<string> >(graphData); - if (!stringData || graphData->times.empty()) - return -1; - int64_t left, right; - double top, bottom; - graph->getExtents(left, right, top, bottom); - double horizScale = (graph->_zoomFactor * graph->_graphWidth - / static_cast<double>(right - left)); - double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); - GraphDataBase::TimeList::iterator lower - = lower_bound(graphData->times.begin(), graphData->times.end(), left); - GraphDataBase::TimeList::iterator upper - = upper_bound(graphData->times.begin(), graphData->times.end(), right); - // easier to transform x,y into graph coordinates - double xgraph, ygraph; - graph->window2GraphCoords(x, y, xgraph, ygraph); - double yrect = eventHeight - 1.5 * graph->_lineWidth; - for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; - ditr != de; - ++ditr) - { - double xrect = (*ditr - left) * horizScale - 1.5 * graph->_lineWidth; - if (xrect <= xgraph && xgraph < xrect + 3.0 * graph->_lineWidth - && yrect <= ygraph && ygraph < yrect + 3.0 * graph->_lineWidth) - return static_cast<ssize_t>(distance(lower, ditr)); - } +ssize_t GraphStyleEvent::dataIndexAtPoint(double x, double y, + shared_ptr<GraphDataBase> graphData, + shared_ptr<Graph> graph) +{ + shared_ptr<GraphData<string> > stringData + = dynamic_pointer_cast<GraphData<string> >(graphData); + if (!stringData || graphData->times.empty()) return -1; - } + int64_t left, right; + double top, bottom; + graph->getExtents(left, right, top, bottom); + double horizScale = (graph->_zoomFactor * graph->_graphWidth + / static_cast<double>(right - left)); + double eventHeight = graph->_graphHeight * (graphData->scale / 100.0); + GraphDataBase::TimeList::iterator lower + = lower_bound(graphData->times.begin(), graphData->times.end(), left); + GraphDataBase::TimeList::iterator upper + = upper_bound(graphData->times.begin(), graphData->times.end(), right); + // easier to transform x,y into graph coordinates + double xgraph, ygraph; + graph->window2GraphCoords(x, y, xgraph, ygraph); + double yrect = eventHeight - 1.5 * graph->_lineWidth; + for (GraphDataBase::TimeList::iterator ditr = lower, de = upper; + ditr != de; + ++ditr) + { + double xrect = (*ditr - left) * horizScale - 1.5 * graph->_lineWidth; + if (xrect <= xgraph && xgraph < xrect + 3.0 * graph->_lineWidth + && yrect <= ygraph && ygraph < yrect + 3.0 * graph->_lineWidth) + return static_cast<ssize_t>(distance(lower, ditr)); + } + return -1; +} } diff --git a/grapher/GraphStyle.hxx b/grapher/GraphStyle.hxx index bea4922a..4924ed2e 100644 --- a/grapher/GraphStyle.hxx +++ b/grapher/GraphStyle.hxx @@ -14,53 +14,53 @@ namespace systemtap { - class GraphDataBase; - class Graph; +class GraphDataBase; +class Graph; - class GraphStyle +class GraphStyle +{ +public: + virtual void draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr) = 0; + virtual ssize_t dataIndexAtPoint(double x, double y, + std::tr1::shared_ptr<GraphDataBase> + graphData, + std::tr1::shared_ptr<Graph> graph) { - public: - virtual void draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr) = 0; - virtual ssize_t dataIndexAtPoint(double x, double y, - std::tr1::shared_ptr<GraphDataBase> - graphData, - std::tr1::shared_ptr<Graph> graph) - { - return -1; - } - }; + return -1; + } +}; - class GraphStyleBar : public GraphStyle - { - public: - void draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr); +class GraphStyleBar : public GraphStyle +{ +public: + void draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr); - static GraphStyleBar instance; - ssize_t dataIndexAtPoint(double x, double y, - std::tr1::shared_ptr<GraphDataBase> graphData, - std::tr1::shared_ptr<Graph> graph); - }; + static GraphStyleBar instance; + ssize_t dataIndexAtPoint(double x, double y, + std::tr1::shared_ptr<GraphDataBase> graphData, + std::tr1::shared_ptr<Graph> graph); +}; - class GraphStyleDot : public GraphStyle - { - public: - void draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr); - static GraphStyleDot instance; - }; +class GraphStyleDot : public GraphStyle +{ +public: + void draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr); + static GraphStyleDot instance; +}; - class GraphStyleEvent : public GraphStyle - { - public: - void draw(std::tr1::shared_ptr<GraphDataBase> graphData, - Graph* graph, Cairo::RefPtr<Cairo::Context> cr); - virtual ssize_t dataIndexAtPoint(double x, double y, - std::tr1::shared_ptr<GraphDataBase> - graphData, - std::tr1::shared_ptr<Graph> graph); - static GraphStyleEvent instance; - }; +class GraphStyleEvent : public GraphStyle +{ +public: + void draw(std::tr1::shared_ptr<GraphDataBase> graphData, + Graph* graph, Cairo::RefPtr<Cairo::Context> cr); + virtual ssize_t dataIndexAtPoint(double x, double y, + std::tr1::shared_ptr<GraphDataBase> + graphData, + std::tr1::shared_ptr<Graph> graph); + static GraphStyleEvent instance; +}; } #endif diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx index bdf60ed2..db7493fb 100644 --- a/grapher/GraphWidget.cxx +++ b/grapher/GraphWidget.cxx @@ -26,388 +26,388 @@ namespace systemtap { - using namespace std; - using namespace std::tr1; +using namespace std; +using namespace std::tr1; - GraphWidget::GraphWidget() - : _trackingDrag(false), _width(600), _height(200), _mouseX(0.0), - _mouseY(0.0), _globalTimeBase(0), _timeBaseInitialized(false) - { - add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK - | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); - Glib::signal_timeout() - .connect(sigc::mem_fun(*this, &GraphWidget::on_timeout), 1000); - signal_expose_event() - .connect(sigc::mem_fun(*this, &GraphWidget::on_expose_event), false); - signal_button_press_event() - .connect(sigc::mem_fun(*this, &GraphWidget::on_button_press_event), - false); - signal_button_release_event() - .connect(sigc::mem_fun(*this, &GraphWidget::on_button_release_event), - false); - signal_motion_notify_event() - .connect(sigc::mem_fun(*this, &GraphWidget::on_motion_notify_event), - false); - signal_scroll_event() - .connect(sigc::mem_fun(*this, &GraphWidget::on_scroll_event), false); - // Temporary testing of multiple graphs - shared_ptr<Graph> graph(new Graph); - _graphs.push_back(graph); - try - { - _refXmlDataDialog = Gnome::Glade::Xml::create(PKGDATADIR "/graph-dialog.glade"); - _refXmlDataDialog->get_widget("dialog1", _dataDialog); - Gtk::Button* button = 0; - _refXmlDataDialog->get_widget("closebutton1", button); - button->signal_clicked() - .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogCancel), - false); - _refXmlDataDialog->get_widget("treeview1", _dataTreeView); - _dataDialog->signal_show() - .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogOpen)); - _dataDialog->signal_hide() - .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogClose)); - _listStore = Gtk::ListStore::create(_dataColumns); - _dataTreeView->set_model(_listStore); - _dataTreeView->append_column_editable("Enabled", - _dataColumns._dataEnabled); - _dataTreeView->append_column("Data", _dataColumns._dataName); - _dataTreeView->append_column("Title", _dataColumns._dataTitle); - // Disable selection in list - Glib::RefPtr<Gtk::TreeSelection> listSelection - = _dataTreeView->get_selection(); - listSelection - ->set_select_function(sigc::mem_fun(*this, - &GraphWidget::no_select_fun)); - _refXmlDataDialog->get_widget("checkbutton1", _relativeTimesButton); - _relativeTimesButton->signal_clicked() - .connect(sigc::mem_fun(*this, - &GraphWidget::onRelativeTimesButtonClicked)); - // Set button's initial value from that in .glade file - _displayRelativeTimes = _relativeTimesButton->get_active(); - graphDataSignal() - .connect(sigc::mem_fun(*this, &GraphWidget::onGraphDataChanged)); - } - catch (const Gnome::Glade::XmlError& ex ) - { - std::cerr << ex.what() << std::endl; - throw; - } - } +GraphWidget::GraphWidget() + : _trackingDrag(false), _width(600), _height(200), _mouseX(0.0), + _mouseY(0.0), _globalTimeBase(0), _timeBaseInitialized(false) +{ + add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK + | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + Glib::signal_timeout() + .connect(sigc::mem_fun(*this, &GraphWidget::on_timeout), 1000); + signal_expose_event() + .connect(sigc::mem_fun(*this, &GraphWidget::on_expose_event), false); + signal_button_press_event() + .connect(sigc::mem_fun(*this, &GraphWidget::on_button_press_event), + false); + signal_button_release_event() + .connect(sigc::mem_fun(*this, &GraphWidget::on_button_release_event), + false); + signal_motion_notify_event() + .connect(sigc::mem_fun(*this, &GraphWidget::on_motion_notify_event), + false); + signal_scroll_event() + .connect(sigc::mem_fun(*this, &GraphWidget::on_scroll_event), false); + // Temporary testing of multiple graphs + shared_ptr<Graph> graph(new Graph); + _graphs.push_back(graph); + try + { + _refXmlDataDialog = Gnome::Glade::Xml::create(PKGDATADIR "/graph-dialog.glade"); + _refXmlDataDialog->get_widget("dialog1", _dataDialog); + Gtk::Button* button = 0; + _refXmlDataDialog->get_widget("closebutton1", button); + button->signal_clicked() + .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogCancel), + false); + _refXmlDataDialog->get_widget("treeview1", _dataTreeView); + _dataDialog->signal_show() + .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogOpen)); + _dataDialog->signal_hide() + .connect(sigc::mem_fun(*this, &GraphWidget::onDataDialogClose)); + _listStore = Gtk::ListStore::create(_dataColumns); + _dataTreeView->set_model(_listStore); + _dataTreeView->append_column_editable("Enabled", + _dataColumns._dataEnabled); + _dataTreeView->append_column("Data", _dataColumns._dataName); + _dataTreeView->append_column("Title", _dataColumns._dataTitle); + // Disable selection in list + Glib::RefPtr<Gtk::TreeSelection> listSelection + = _dataTreeView->get_selection(); + listSelection + ->set_select_function(sigc::mem_fun(*this, + &GraphWidget::no_select_fun)); + _refXmlDataDialog->get_widget("checkbutton1", _relativeTimesButton); + _relativeTimesButton->signal_clicked() + .connect(sigc::mem_fun(*this, + &GraphWidget::onRelativeTimesButtonClicked)); + // Set button's initial value from that in .glade file + _displayRelativeTimes = _relativeTimesButton->get_active(); + graphDataSignal() + .connect(sigc::mem_fun(*this, &GraphWidget::onGraphDataChanged)); + } + catch (const Gnome::Glade::XmlError& ex ) + { + std::cerr << ex.what() << std::endl; + throw; + } +} - GraphWidget::~GraphWidget() - { - } +GraphWidget::~GraphWidget() +{ +} - void GraphWidget::onGraphDataChanged() - { - // add any new graph data to the last graph - GraphDataList newData; - GraphDataList& allData = getGraphData(); - for (GraphDataList::iterator gditr = allData.begin(), gdend = allData.end(); - gditr != gdend; - ++gditr) - { - bool found = false; - for (GraphList::iterator gitr = _graphs.begin(), gend = _graphs.end(); - gitr != gend; - ++gitr) - { - GraphDataList& gdata = (*gitr)->getDatasets(); - if (find(gdata.begin(), gdata.end(), *gditr) != gdata.end()) - { - found = true; - break; - } - } - if (!found) - newData.push_back(*gditr); - } - copy(newData.begin(), newData.end(), - back_inserter(_graphs.back()->getDatasets())); - } +void GraphWidget::onGraphDataChanged() +{ + // add any new graph data to the last graph + GraphDataList newData; + GraphDataList& allData = getGraphData(); + for (GraphDataList::iterator gditr = allData.begin(), gdend = allData.end(); + gditr != gdend; + ++gditr) + { + bool found = false; + for (GraphList::iterator gitr = _graphs.begin(), gend = _graphs.end(); + gitr != gend; + ++gitr) + { + GraphDataList& gdata = (*gitr)->getDatasets(); + if (find(gdata.begin(), gdata.end(), *gditr) != gdata.end()) + { + found = true; + break; + } + } + if (!found) + newData.push_back(*gditr); + } + copy(newData.begin(), newData.end(), + back_inserter(_graphs.back()->getDatasets())); +} - void GraphWidget::addGraph() - { - double x = 0.0; - double y = 0.0; - if (!_graphs.empty()) - { - _graphs.back()->getOrigin(x, y); - y += _graphs.back()->_height + 10; - } - shared_ptr<Graph> graph(new Graph(x, y)); - _height = y + graph->_height; - graph->setOrigin(x, y); - graph->_timeBase = _globalTimeBase; - _graphs.push_back(graph); - queue_resize(); - } +void GraphWidget::addGraph() +{ + double x = 0.0; + double y = 0.0; + if (!_graphs.empty()) + { + _graphs.back()->getOrigin(x, y); + y += _graphs.back()->_height + 10; + } + shared_ptr<Graph> graph(new Graph(x, y)); + _height = y + graph->_height; + graph->setOrigin(x, y); + graph->_timeBase = _globalTimeBase; + _graphs.push_back(graph); + queue_resize(); +} - bool GraphWidget::on_expose_event(GdkEventExpose* event) - { - // This is where we draw on the window - Glib::RefPtr<Gdk::Window> window = get_window(); - if(!window) - return true; - - Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context(); - cr->save(); - cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); - cr->paint(); - if (!_timeBaseInitialized && !getGraphData().empty()) - { - GraphDataList& graphData = getGraphData(); - int64_t earliest = INT64_MAX; - for (GraphDataList::iterator gd = graphData.begin(), - end = graphData.end(); - gd != end; - ++gd) - { - if (!(*gd)->times.empty() && (*gd)->times[0] < earliest) - earliest = (*gd)->times[0]; - } - if (earliest != INT64_MAX) - { - _globalTimeBase = earliest; - _timeBaseInitialized = true; - } - } - for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) - { - if (_displayRelativeTimes && _timeBaseInitialized) - (*g)->_timeBase = _globalTimeBase; - else - (*g)->_timeBase = 0.0; - double x, y; - (*g)->getOrigin(x, y); - cr->save(); - cr->translate(x, y); - (*g)->draw(cr); - cr->restore(); - } - if (_hoverText && _hoverText->isVisible()) - _hoverText->draw(cr); - cr->restore(); +bool GraphWidget::on_expose_event(GdkEventExpose* event) +{ + // This is where we draw on the window + Glib::RefPtr<Gdk::Window> window = get_window(); + if(!window) return true; - } - bool GraphWidget::on_button_press_event(GdkEventButton* event) - { - shared_ptr<Graph> g = getGraphUnderPoint(event->x, event->y); - if (g) - { - _activeGraph = g; - if (event->button == 3) - { - _dataDialog->show(); - return true; - } - } - if (!_activeGraph) - return true; - double activeX, activeY; - _activeGraph->getOrigin(activeX, activeY); - if (!_activeGraph->_autoScrolling - && _activeGraph->_playButton->containsPoint(event->x - activeX, - event->y - activeY)) - { - _activeGraph->_autoScaling = true; - _activeGraph->_autoScrolling = true; - queue_draw(); - } - else - { - _trackingDrag = true; - _activeGraph->_autoScaling = false; - _activeGraph->_autoScrolling = false; - _dragOriginX = event->x; - _dragOriginY = event->y; - _dragOrigLeft = _activeGraph->_left; - _dragOrigRight = _activeGraph->_right; - establishHoverTimeout(); - } - return true; - } + Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context(); + cr->save(); + cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); + cr->paint(); + if (!_timeBaseInitialized && !getGraphData().empty()) + { + GraphDataList& graphData = getGraphData(); + int64_t earliest = INT64_MAX; + for (GraphDataList::iterator gd = graphData.begin(), + end = graphData.end(); + gd != end; + ++gd) + { + if (!(*gd)->times.empty() && (*gd)->times[0] < earliest) + earliest = (*gd)->times[0]; + } + if (earliest != INT64_MAX) + { + _globalTimeBase = earliest; + _timeBaseInitialized = true; + } + } + for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) + { + if (_displayRelativeTimes && _timeBaseInitialized) + (*g)->_timeBase = _globalTimeBase; + else + (*g)->_timeBase = 0.0; + double x, y; + (*g)->getOrigin(x, y); + cr->save(); + cr->translate(x, y); + (*g)->draw(cr); + cr->restore(); + } + if (_hoverText && _hoverText->isVisible()) + _hoverText->draw(cr); + cr->restore(); + return true; +} - bool GraphWidget::on_button_release_event(GdkEventButton* event) - { - // Was data dialog launched? - if (event->button != 3) - { - _activeGraph.reset(); - _trackingDrag = false; - } +bool GraphWidget::on_button_press_event(GdkEventButton* event) +{ + shared_ptr<Graph> g = getGraphUnderPoint(event->x, event->y); + if (g) + { + _activeGraph = g; + if (event->button == 3) + { + _dataDialog->show(); + return true; + } + } + if (!_activeGraph) return true; - } - - bool GraphWidget::on_motion_notify_event(GdkEventMotion* event) - { - Glib::RefPtr<Gdk::Window> win = get_window(); - if(!win) - return true; - _mouseX = event->x; - _mouseY = event->y; - if (_trackingDrag && _activeGraph) - { - Gtk::Allocation allocation = get_allocation(); - const int width = allocation.get_width(); - double motion = (_mouseX - _dragOriginX) / (double) width; - double increment = motion * (_dragOrigLeft - _dragOrigRight); - _activeGraph->_left = _dragOrigLeft + increment; - _activeGraph->_right = _dragOrigRight + increment; - queue_draw(); - } - if (_hoverText && _hoverText->isVisible()) - { - _hoverText->setVisible(false); - queue_draw(); - } - establishHoverTimeout(); + double activeX, activeY; + _activeGraph->getOrigin(activeX, activeY); + if (!_activeGraph->_autoScrolling + && _activeGraph->_playButton->containsPoint(event->x - activeX, + event->y - activeY)) + { + _activeGraph->_autoScaling = true; + _activeGraph->_autoScrolling = true; + queue_draw(); + } + else + { + _trackingDrag = true; + _activeGraph->_autoScaling = false; + _activeGraph->_autoScrolling = false; + _dragOriginX = event->x; + _dragOriginY = event->y; + _dragOrigLeft = _activeGraph->_left; + _dragOrigRight = _activeGraph->_right; + establishHoverTimeout(); + } + return true; +} +bool GraphWidget::on_button_release_event(GdkEventButton* event) +{ + // Was data dialog launched? + if (event->button != 3) + { + _activeGraph.reset(); + _trackingDrag = false; + } + return true; +} + +bool GraphWidget::on_motion_notify_event(GdkEventMotion* event) +{ + Glib::RefPtr<Gdk::Window> win = get_window(); + if(!win) return true; - } + _mouseX = event->x; + _mouseY = event->y; + if (_trackingDrag && _activeGraph) + { + Gtk::Allocation allocation = get_allocation(); + const int width = allocation.get_width(); + double motion = (_mouseX - _dragOriginX) / (double) width; + double increment = motion * (_dragOrigLeft - _dragOrigRight); + _activeGraph->_left = _dragOrigLeft + increment; + _activeGraph->_right = _dragOrigRight + increment; + queue_draw(); + } + if (_hoverText && _hoverText->isVisible()) + { + _hoverText->setVisible(false); + queue_draw(); + } + establishHoverTimeout(); - bool GraphWidget::on_scroll_event(GdkEventScroll* event) - { - for (GraphList::iterator gitr = _graphs.begin(); - gitr != _graphs.end(); - ++gitr) - { - if ((*gitr)->containsPoint(event->x, event->y)) - { - if (event->direction == GDK_SCROLL_UP) - (*gitr)->_zoomFactor += .1; - else if (event->direction == GDK_SCROLL_DOWN) - (*gitr)->_zoomFactor -= .1; - queue_draw(); - break; - } - } - return true; - } + return true; +} - bool GraphWidget::on_timeout() - { - queue_draw(); - return true; - } +bool GraphWidget::on_scroll_event(GdkEventScroll* event) +{ + for (GraphList::iterator gitr = _graphs.begin(); + gitr != _graphs.end(); + ++gitr) + { + if ((*gitr)->containsPoint(event->x, event->y)) + { + if (event->direction == GDK_SCROLL_UP) + (*gitr)->_zoomFactor += .1; + else if (event->direction == GDK_SCROLL_DOWN) + (*gitr)->_zoomFactor -= .1; + queue_draw(); + break; + } + } + return true; +} - void GraphWidget::on_size_request(Gtk::Requisition* req) - { - req->width = _width; - req->height = _height; - } +bool GraphWidget::on_timeout() +{ + queue_draw(); + return true; +} - void GraphWidget::onDataDialogCancel() - { - _dataDialog->hide(); - } +void GraphWidget::on_size_request(Gtk::Requisition* req) +{ + req->width = _width; + req->height = _height; +} + +void GraphWidget::onDataDialogCancel() +{ + _dataDialog->hide(); +} - void GraphWidget::onDataDialogOpen() - { - _listStore->clear(); - for (GraphDataList::iterator itr = getGraphData().begin(), - end = getGraphData().end(); - itr != end; - ++itr) - { - Gtk::TreeModel::iterator litr = _listStore->append(); - Gtk::TreeModel::Row row = *litr; - row[_dataColumns._dataName] = (*itr)->name; - if (!(*itr)->title.empty()) - row[_dataColumns._dataTitle] = (*itr)->title; - row[_dataColumns._graphData] = *itr; - GraphDataList& gsets = _activeGraph->getDatasets(); - GraphDataList::iterator setItr - = find(gsets.begin(), gsets.end(), *itr); - row[_dataColumns._dataEnabled] = (setItr != gsets.end()); - } - _listConnection =_listStore->signal_row_changed() - .connect(sigc::mem_fun(*this, &GraphWidget::onRowChanged)); +void GraphWidget::onDataDialogOpen() +{ + _listStore->clear(); + for (GraphDataList::iterator itr = getGraphData().begin(), + end = getGraphData().end(); + itr != end; + ++itr) + { + Gtk::TreeModel::iterator litr = _listStore->append(); + Gtk::TreeModel::Row row = *litr; + row[_dataColumns._dataName] = (*itr)->name; + if (!(*itr)->title.empty()) + row[_dataColumns._dataTitle] = (*itr)->title; + row[_dataColumns._graphData] = *itr; + GraphDataList& gsets = _activeGraph->getDatasets(); + GraphDataList::iterator setItr + = find(gsets.begin(), gsets.end(), *itr); + row[_dataColumns._dataEnabled] = (setItr != gsets.end()); + } + _listConnection =_listStore->signal_row_changed() + .connect(sigc::mem_fun(*this, &GraphWidget::onRowChanged)); - } +} - void GraphWidget::onDataDialogClose() - { - if (_listConnection.connected()) - _listConnection.disconnect(); - } +void GraphWidget::onDataDialogClose() +{ + if (_listConnection.connected()) + _listConnection.disconnect(); +} - bool GraphWidget::onHoverTimeout() - { - shared_ptr<Graph> g = getGraphUnderPoint(_mouseX, _mouseY); - if (g && !g->_autoScrolling) - { - if (!_hoverText) - _hoverText = shared_ptr<CairoTextBox>(new CairoTextBox()); - _hoverText->setOrigin(_mouseX + 10, _mouseY - 5); - GraphDataList& dataSets = g->getDatasets(); - for (GraphDataList::reverse_iterator ritr = dataSets.rbegin(), - end = dataSets.rend(); - ritr != end; - ++ritr) +bool GraphWidget::onHoverTimeout() +{ + shared_ptr<Graph> g = getGraphUnderPoint(_mouseX, _mouseY); + if (g && !g->_autoScrolling) + { + if (!_hoverText) + _hoverText = shared_ptr<CairoTextBox>(new CairoTextBox()); + _hoverText->setOrigin(_mouseX + 10, _mouseY - 5); + GraphDataList& dataSets = g->getDatasets(); + for (GraphDataList::reverse_iterator ritr = dataSets.rbegin(), + end = dataSets.rend(); + ritr != end; + ++ritr) { - ssize_t index - = (*ritr)->style->dataIndexAtPoint(_mouseX, _mouseY, *ritr, g); - if (index >= 0) + 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; + _hoverText->contents = (*ritr)->name + + ": " + (*ritr)->elementAsString(index); + _hoverText->setVisible(true); + queue_draw(); + break; } } - } - return false; - } + } + return false; +} - shared_ptr<Graph> GraphWidget::getGraphUnderPoint(double x, double y) - { - for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) - { - if (x >= (*g)->_graphX - && x < (*g)->_graphX + (*g)->_graphWidth - && y >= (*g)->_graphY - && y < (*g)->_graphY + (*g)->_graphHeight) - return *g; - } - return shared_ptr<Graph>(); - } +shared_ptr<Graph> GraphWidget::getGraphUnderPoint(double x, double y) +{ + for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g) + { + if (x >= (*g)->_graphX + && x < (*g)->_graphX + (*g)->_graphWidth + && y >= (*g)->_graphY + && y < (*g)->_graphY + (*g)->_graphHeight) + return *g; + } + return shared_ptr<Graph>(); +} - void GraphWidget::establishHoverTimeout() - { - if (_hover_timeout_connection.connected()) - _hover_timeout_connection.disconnect(); - _hover_timeout_connection = Glib::signal_timeout() - .connect(sigc::mem_fun(*this, &GraphWidget::onHoverTimeout), 1000); - } +void GraphWidget::establishHoverTimeout() +{ + if (_hover_timeout_connection.connected()) + _hover_timeout_connection.disconnect(); + _hover_timeout_connection = Glib::signal_timeout() + .connect(sigc::mem_fun(*this, &GraphWidget::onHoverTimeout), 1000); +} - void GraphWidget::onRelativeTimesButtonClicked() - { - _displayRelativeTimes = _relativeTimesButton->get_active(); - queue_draw(); - } +void GraphWidget::onRelativeTimesButtonClicked() +{ + _displayRelativeTimes = _relativeTimesButton->get_active(); + queue_draw(); +} - void GraphWidget::onRowChanged(const Gtk::TreeModel::Path&, - const Gtk::TreeModel::iterator& litr) - { - Gtk::TreeModel::Row row = *litr; - bool val = row[_dataColumns._dataEnabled]; - shared_ptr<GraphDataBase> data = row[_dataColumns._graphData]; - GraphDataList& graphData = _activeGraph->getDatasets(); - if (val - && find(graphData.begin(), graphData.end(), data) == graphData.end()) - { - _activeGraph->addGraphData(data); - } - else if (!val) - { - graphData.erase(remove(graphData.begin(), graphData.end(), data), - graphData.end()); - } - } +void GraphWidget::onRowChanged(const Gtk::TreeModel::Path&, + const Gtk::TreeModel::iterator& litr) +{ + Gtk::TreeModel::Row row = *litr; + bool val = row[_dataColumns._dataEnabled]; + shared_ptr<GraphDataBase> data = row[_dataColumns._graphData]; + GraphDataList& graphData = _activeGraph->getDatasets(); + if (val + && find(graphData.begin(), graphData.end(), data) == graphData.end()) + { + _activeGraph->addGraphData(data); + } + else if (!val) + { + graphData.erase(remove(graphData.begin(), graphData.end(), data), + graphData.end()); + } +} } diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx index 89b86db9..f90da361 100644 --- a/grapher/GraphWidget.hxx +++ b/grapher/GraphWidget.hxx @@ -19,84 +19,84 @@ namespace systemtap { - class CairoPlayButton; +class CairoPlayButton; - class DataModelColumns : public Gtk::TreeModelColumnRecord +class DataModelColumns : public Gtk::TreeModelColumnRecord +{ +public: + DataModelColumns() { - public: - DataModelColumns() - { - add(_dataEnabled); - add(_dataName); - add(_dataTitle); - add(_graphData); - } - Gtk::TreeModelColumn<bool> _dataEnabled; - Gtk::TreeModelColumn<Glib::ustring> _dataName; - Gtk::TreeModelColumn<Glib::ustring> _dataTitle; - Gtk::TreeModelColumn<std::tr1::shared_ptr<GraphDataBase> > _graphData; - }; + add(_dataEnabled); + add(_dataName); + add(_dataTitle); + add(_graphData); + } + Gtk::TreeModelColumn<bool> _dataEnabled; + Gtk::TreeModelColumn<Glib::ustring> _dataName; + Gtk::TreeModelColumn<Glib::ustring> _dataTitle; + Gtk::TreeModelColumn<std::tr1::shared_ptr<GraphDataBase> > _graphData; +}; - class GraphWidget : public Gtk::DrawingArea - { - public: - GraphWidget(); - virtual ~GraphWidget(); - void addGraph(); +class GraphWidget : public Gtk::DrawingArea +{ +public: + GraphWidget(); + virtual ~GraphWidget(); + void addGraph(); - protected: - typedef std::vector<std::tr1::shared_ptr<Graph> > GraphList; - GraphList _graphs; - // For click and drag - std::tr1::shared_ptr<Graph> _activeGraph; - // Dragging all graphs simultaneously, or perhaps seperately - typedef std::vector<std::pair<double, double> > DragList; - DragList dragCoords; - //Override default signal handler: - virtual bool on_expose_event(GdkEventExpose* event); - virtual bool on_motion_notify_event(GdkEventMotion* event); - virtual bool on_button_press_event(GdkEventButton* event); - virtual bool on_button_release_event(GdkEventButton* event); - virtual bool on_scroll_event(GdkEventScroll* event); - bool on_timeout(); - virtual void on_size_request(Gtk::Requisition* req); - bool _trackingDrag; - double _dragOriginX; - double _dragOriginY; - double _dragOrigLeft; - double _dragOrigRight; - double _width; - double _height; - Glib::RefPtr<Gnome::Glade::Xml> _refXmlDataDialog; - Gtk::Dialog* _dataDialog; - Gtk::TreeView* _dataTreeView; - void onDataDialogCancel(); - void onDataDialogOpen(); - void onDataDialogClose(); - bool onHoverTimeout(); - DataModelColumns _dataColumns; - Glib::RefPtr<Gtk::ListStore> _listStore; - sigc::connection _hover_timeout_connection; - std::tr1::shared_ptr<CairoTextBox> _hoverText; - double _mouseX; - double _mouseY; - int64_t _globalTimeBase; - bool _timeBaseInitialized; - std::tr1::shared_ptr<Graph> getGraphUnderPoint(double x, double y); - void establishHoverTimeout(); - Gtk::CheckButton* _relativeTimesButton; - bool _displayRelativeTimes; - void onRelativeTimesButtonClicked(); - void onRowChanged(const Gtk::TreeModel::Path&, - const Gtk::TreeModel::iterator&); - sigc::connection _listConnection; - bool no_select_fun(const Glib::RefPtr<Gtk::TreeModel>& model, - const Gtk::TreeModel::Path& path, - bool) - { - return false; - } - void onGraphDataChanged(); - }; +protected: + typedef std::vector<std::tr1::shared_ptr<Graph> > GraphList; + GraphList _graphs; + // For click and drag + std::tr1::shared_ptr<Graph> _activeGraph; + // Dragging all graphs simultaneously, or perhaps seperately + typedef std::vector<std::pair<double, double> > DragList; + DragList dragCoords; + //Override default signal handler: + virtual bool on_expose_event(GdkEventExpose* event); + virtual bool on_motion_notify_event(GdkEventMotion* event); + virtual bool on_button_press_event(GdkEventButton* event); + virtual bool on_button_release_event(GdkEventButton* event); + virtual bool on_scroll_event(GdkEventScroll* event); + bool on_timeout(); + virtual void on_size_request(Gtk::Requisition* req); + bool _trackingDrag; + double _dragOriginX; + double _dragOriginY; + double _dragOrigLeft; + double _dragOrigRight; + double _width; + double _height; + Glib::RefPtr<Gnome::Glade::Xml> _refXmlDataDialog; + Gtk::Dialog* _dataDialog; + Gtk::TreeView* _dataTreeView; + void onDataDialogCancel(); + void onDataDialogOpen(); + void onDataDialogClose(); + bool onHoverTimeout(); + DataModelColumns _dataColumns; + Glib::RefPtr<Gtk::ListStore> _listStore; + sigc::connection _hover_timeout_connection; + std::tr1::shared_ptr<CairoTextBox> _hoverText; + double _mouseX; + double _mouseY; + int64_t _globalTimeBase; + bool _timeBaseInitialized; + std::tr1::shared_ptr<Graph> getGraphUnderPoint(double x, double y); + void establishHoverTimeout(); + Gtk::CheckButton* _relativeTimesButton; + bool _displayRelativeTimes; + void onRelativeTimesButtonClicked(); + void onRowChanged(const Gtk::TreeModel::Path&, + const Gtk::TreeModel::iterator&); + sigc::connection _listConnection; + bool no_select_fun(const Glib::RefPtr<Gtk::TreeModel>& model, + const Gtk::TreeModel::Path& path, + bool) + { + return false; + } + void onGraphDataChanged(); +}; } #endif // SYSTEMTAP_GRAPHWIDGET_H diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index 2595e8cc..803b5fb3 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -22,22 +22,22 @@ namespace systemtap { - using namespace std; - using namespace std::tr1; +using namespace std; +using namespace std::tr1; - sigc::signal<void, pid_t>& childDiedSignal() - { - static sigc::signal<void, pid_t> deathSignal; - return deathSignal; - } +sigc::signal<void, pid_t>& childDiedSignal() +{ + static sigc::signal<void, pid_t> deathSignal; + return deathSignal; +} - ParserList parsers; +ParserList parsers; - sigc::signal<void>& parserListChangedSignal() - { - static sigc::signal<void> listChangedSignal; - return listChangedSignal; - } +sigc::signal<void>& parserListChangedSignal() +{ + static sigc::signal<void> listChangedSignal; + return listChangedSignal; +} vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range) { @@ -47,263 +47,263 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range) return result; } - void StapParser::parseData(shared_ptr<GraphDataBase> gdata, - int64_t time, const string& dataString) - { - std::istringstream stream(dataString); - shared_ptr<GraphData<double> > dblptr; - shared_ptr<GraphData<string> > strptr; - dblptr = dynamic_pointer_cast<GraphData<double> >(gdata); - if (dblptr) - { - double data; - stream >> data; - dblptr->times.push_back(time); - dblptr->data.push_back(data); - } - else if ((strptr = dynamic_pointer_cast<GraphData<string> >(gdata)) - != 0) - { - strptr->times.push_back(time); - strptr->data.push_back(dataString); - } - } +void StapParser::parseData(shared_ptr<GraphDataBase> gdata, + int64_t time, const string& dataString) +{ + std::istringstream stream(dataString); + shared_ptr<GraphData<double> > dblptr; + shared_ptr<GraphData<string> > strptr; + dblptr = dynamic_pointer_cast<GraphData<double> >(gdata); + if (dblptr) + { + double data; + stream >> data; + dblptr->times.push_back(time); + dblptr->data.push_back(data); + } + else if ((strptr = dynamic_pointer_cast<GraphData<string> >(gdata)) + != 0) + { + strptr->times.push_back(time); + strptr->data.push_back(dataString); + } +} - bool findTaggedValue(const string& src, const char* tag, string& result) - { - using namespace boost; - sub_range<const string> found = find_first(src, tag); - if (found.empty()) - return false; - result.insert(result.end(),found.end(), src.end()); - return true; - } +bool findTaggedValue(const string& src, const char* tag, string& result) +{ + using namespace boost; + sub_range<const string> found = find_first(src, tag); + if (found.empty()) + return false; + result.insert(result.end(),found.end(), src.end()); + return true; +} - bool StapParser::ioCallback(Glib::IOCondition ioCondition) - { - using namespace std; - using std::tr1::shared_ptr; - using namespace boost; - if (ioCondition & Glib::IO_HUP) - { - if (_catchHUP) - { - childDiedSignal().emit(getPid()); - _ioConnection.disconnect(); - _errIoConnection.disconnect(); - } - return true; - } - if ((ioCondition & Glib::IO_IN) == 0) +bool StapParser::ioCallback(Glib::IOCondition ioCondition) +{ + using namespace std; + using std::tr1::shared_ptr; + using namespace boost; + if (ioCondition & Glib::IO_HUP) + { + if (_catchHUP) + { + childDiedSignal().emit(getPid()); + _ioConnection.disconnect(); + _errIoConnection.disconnect(); + } return true; - char buf[256]; - ssize_t bytes_read = 0; - bytes_read = read(_inFd, buf, sizeof(buf) - 1); - if (bytes_read <= 0) - { - childDiedSignal().emit(getPid()); - return true; - } - _buffer.append(buf, bytes_read); - string::size_type ret = string::npos; - while ((ret = _buffer.find(_lineEndChar)) != string::npos) - { - Glib::ustring dataString(_buffer, 0, ret); - // %DataSet and %CSV declare a data set; all other - // statements begin with the name of a data set. - // Except %LineEnd :) - sub_range<Glib::ustring> found; - if (dataString[0] == '%') - { - if ((found = find_first(dataString, "%DataSet:"))) - { - string setName; - int hexColor; - double scale; - string style; - istringstream stream(Glib::ustring(found.end(), - dataString.end())); - stream >> setName >> scale >> std::hex >> hexColor - >> style; - if (style == "bar" || style == "dot") - { - std::tr1::shared_ptr<GraphData<double> > - dataSet(new GraphData<double>); - dataSet->name = setName; - if (style == "dot") - dataSet->style = &GraphStyleDot::instance; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - dataSet->scale = scale; - _dataSets.insert(std::make_pair(setName, dataSet)); - getGraphData().push_back(dataSet); - graphDataSignal().emit(); - } - else if (style == "discreet") - { - std::tr1::shared_ptr<GraphData<string> > - dataSet(new GraphData<string>); - dataSet->name = setName; - dataSet->style = &GraphStyleEvent::instance; - dataSet->color[0] = (hexColor >> 16) / 255.0; - dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; - dataSet->color[2] = (hexColor & 0xff) / 255.0; - dataSet->scale = scale; - _dataSets.insert(std::make_pair(setName, dataSet)); - getGraphData().push_back(dataSet); - graphDataSignal().emit(); - } - } - else if ((found = find_first(dataString, "%CSV:"))) - { - vector<string> tokens - = commaSplit(sub_range<Glib::ustring>(found.end(), - dataString.end())); - for (vector<string>::iterator tokIter = tokens.begin(), - e = tokens.end(); - tokIter != e; - ++tokIter) - { - DataMap::iterator setIter = _dataSets.find(*tokIter); - if (setIter != _dataSets.end()) - _csv.elements - .push_back(CSVData::Element(*tokIter, - setIter->second)); - } - } - else if ((found = find_first(dataString, "%LineEnd:"))) - { - istringstream stream(Glib::ustring(found.end(), - dataString.end())); - int charAsInt = 0; - // parse hex and octal numbers too - stream >> std::setbase(0) >> charAsInt; - _lineEndChar = static_cast<char>(charAsInt); - } - else - { - cerr << "Unknown declaration " << dataString << endl; - } - } - else - { - std::istringstream stream(dataString); - string setName; - stream >> setName; - DataMap::iterator itr = _dataSets.find(setName); - if (itr != _dataSets.end()) - { - shared_ptr<GraphDataBase> gdata = itr->second; - string decl; - // Hack: scan from the beginning of dataString again - if (findTaggedValue(dataString, "%Title:", decl)) - { - gdata->title = decl; - } - else if (findTaggedValue(dataString, "%XAxisTitle:", decl)) - { - gdata->xAxisText = decl; - } - else if (findTaggedValue(dataString, "%YAxisTitle:", decl)) - { - gdata->yAxisText = decl; - } - else if ((found = find_first(dataString, "%YMax:"))) - { - double ymax; - std::istringstream - stream(Glib::ustring(found.end(), dataString.end())); - stream >> ymax; - gdata->scale = ymax; - } - else - { - if (!_csv.elements.empty()) - { - vector<string> tokens = commaSplit(dataString); - int i = 0; - int64_t time; - vector<string>::iterator tokIter = tokens.begin(); - std::istringstream timeStream(*tokIter++); - timeStream >> time; - for (vector<string>::iterator e = tokens.end(); - tokIter != e; - ++tokIter, ++i) - { - parseData(_csv.elements[i].second, time, - *tokIter); - } - } - else - { - int64_t time; - stringbuf data; - stream >> time; - stream.get(data, _lineEndChar); - parseData(itr->second, time, data.str()); - } - } - } - } - _buffer.erase(0, ret + 1); - } + } + if ((ioCondition & Glib::IO_IN) == 0) return true; - } - - bool StapParser::errIoCallback(Glib::IOCondition ioCondition) - { - using namespace std; - if ((ioCondition & Glib::IO_IN) == 0) + char buf[256]; + ssize_t bytes_read = 0; + bytes_read = read(_inFd, buf, sizeof(buf) - 1); + if (bytes_read <= 0) + { + childDiedSignal().emit(getPid()); return true; - char buf[256]; - ssize_t bytes_read = 0; - bytes_read = read(_errFd, buf, sizeof(buf) - 1); - if (bytes_read <= 0) - { - cerr << "StapParser: error reading from stderr!\n"; - return true; - } - if (write(STDERR_FILENO, buf, bytes_read) < 0) - ; + } + _buffer.append(buf, bytes_read); + string::size_type ret = string::npos; + while ((ret = _buffer.find(_lineEndChar)) != string::npos) + { + Glib::ustring dataString(_buffer, 0, ret); + // %DataSet and %CSV declare a data set; all other + // statements begin with the name of a data set. + // Except %LineEnd :) + sub_range<Glib::ustring> found; + if (dataString[0] == '%') + { + if ((found = find_first(dataString, "%DataSet:"))) + { + string setName; + int hexColor; + double scale; + string style; + istringstream stream(Glib::ustring(found.end(), + dataString.end())); + stream >> setName >> scale >> std::hex >> hexColor + >> style; + if (style == "bar" || style == "dot") + { + std::tr1::shared_ptr<GraphData<double> > + dataSet(new GraphData<double>); + dataSet->name = setName; + if (style == "dot") + dataSet->style = &GraphStyleDot::instance; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + getGraphData().push_back(dataSet); + graphDataSignal().emit(); + } + else if (style == "discreet") + { + std::tr1::shared_ptr<GraphData<string> > + dataSet(new GraphData<string>); + dataSet->name = setName; + dataSet->style = &GraphStyleEvent::instance; + dataSet->color[0] = (hexColor >> 16) / 255.0; + dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0; + dataSet->color[2] = (hexColor & 0xff) / 255.0; + dataSet->scale = scale; + _dataSets.insert(std::make_pair(setName, dataSet)); + getGraphData().push_back(dataSet); + graphDataSignal().emit(); + } + } + else if ((found = find_first(dataString, "%CSV:"))) + { + vector<string> tokens + = commaSplit(sub_range<Glib::ustring>(found.end(), + dataString.end())); + for (vector<string>::iterator tokIter = tokens.begin(), + e = tokens.end(); + tokIter != e; + ++tokIter) + { + DataMap::iterator setIter = _dataSets.find(*tokIter); + if (setIter != _dataSets.end()) + _csv.elements + .push_back(CSVData::Element(*tokIter, + setIter->second)); + } + } + else if ((found = find_first(dataString, "%LineEnd:"))) + { + istringstream stream(Glib::ustring(found.end(), + dataString.end())); + int charAsInt = 0; + // parse hex and octal numbers too + stream >> std::setbase(0) >> charAsInt; + _lineEndChar = static_cast<char>(charAsInt); + } + else + { + cerr << "Unknown declaration " << dataString << endl; + } + } + else + { + std::istringstream stream(dataString); + string setName; + stream >> setName; + DataMap::iterator itr = _dataSets.find(setName); + if (itr != _dataSets.end()) + { + shared_ptr<GraphDataBase> gdata = itr->second; + string decl; + // Hack: scan from the beginning of dataString again + if (findTaggedValue(dataString, "%Title:", decl)) + { + gdata->title = decl; + } + else if (findTaggedValue(dataString, "%XAxisTitle:", decl)) + { + gdata->xAxisText = decl; + } + else if (findTaggedValue(dataString, "%YAxisTitle:", decl)) + { + gdata->yAxisText = decl; + } + else if ((found = find_first(dataString, "%YMax:"))) + { + double ymax; + std::istringstream + stream(Glib::ustring(found.end(), dataString.end())); + stream >> ymax; + gdata->scale = ymax; + } + else + { + if (!_csv.elements.empty()) + { + vector<string> tokens = commaSplit(dataString); + int i = 0; + int64_t time; + vector<string>::iterator tokIter = tokens.begin(); + std::istringstream timeStream(*tokIter++); + timeStream >> time; + for (vector<string>::iterator e = tokens.end(); + tokIter != e; + ++tokIter, ++i) + { + parseData(_csv.elements[i].second, time, + *tokIter); + } + } + else + { + int64_t time; + stringbuf data; + stream >> time; + stream.get(data, _lineEndChar); + parseData(itr->second, time, data.str()); + } + } + } + } + _buffer.erase(0, ret + 1); + } + return true; +} + +bool StapParser::errIoCallback(Glib::IOCondition ioCondition) +{ + using namespace std; + if ((ioCondition & Glib::IO_IN) == 0) return true; - } + char buf[256]; + ssize_t bytes_read = 0; + bytes_read = read(_errFd, buf, sizeof(buf) - 1); + if (bytes_read <= 0) + { + cerr << "StapParser: error reading from stderr!\n"; + return true; + } + if (write(STDERR_FILENO, buf, bytes_read) < 0) + ; + return true; +} - void StapParser::initIo(int inFd, int errFd, bool catchHUP) - { - _inFd = inFd; - _errFd = errFd; - _catchHUP = catchHUP; - Glib::IOCondition inCond = Glib::IO_IN; - if (catchHUP) - inCond |= Glib::IO_HUP; - if (_errFd >= 0) - { - _errIoConnection = Glib::signal_io() - .connect(sigc::mem_fun(*this, &StapParser::errIoCallback), - _errFd, Glib::IO_IN); - } - _ioConnection = Glib::signal_io() - .connect(sigc::mem_fun(*this, &StapParser::ioCallback), - _inFd, inCond); +void StapParser::initIo(int inFd, int errFd, bool catchHUP) +{ + _inFd = inFd; + _errFd = errFd; + _catchHUP = catchHUP; + Glib::IOCondition inCond = Glib::IO_IN; + if (catchHUP) + inCond |= Glib::IO_HUP; + if (_errFd >= 0) + { + _errIoConnection = Glib::signal_io() + .connect(sigc::mem_fun(*this, &StapParser::errIoCallback), + _errFd, Glib::IO_IN); + } + _ioConnection = Glib::signal_io() + .connect(sigc::mem_fun(*this, &StapParser::ioCallback), + _inFd, inCond); - } +} - void StapParser::disconnect() - { - if (_ioConnection.connected()) - _ioConnection.disconnect(); - if (_errIoConnection.connected()) - _errIoConnection.disconnect(); - if (_inFd >= 0) - { - close(_inFd); - _inFd = -1; - } - if (_errFd >= 0) - { - close(_errFd); - _errFd = -1; - } - } +void StapParser::disconnect() +{ + if (_ioConnection.connected()) + _ioConnection.disconnect(); + if (_errIoConnection.connected()) + _errIoConnection.disconnect(); + if (_inFd >= 0) + { + close(_inFd); + _inFd = -1; + } + if (_errFd >= 0) + { + close(_errFd); + _errFd = -1; + } +} } diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx index 169533b6..b410ab18 100644 --- a/grapher/StapParser.hxx +++ b/grapher/StapParser.hxx @@ -15,65 +15,65 @@ namespace systemtap { - // arguments and script for a stap process - struct StapProcess - { - StapProcess(pid_t pid_ = -1) : argv(0), pid(pid_) {} - std::string stapArgs; - std::string script; - std::string scriptArgs; - // arguments passed from a single array, like from the command line. - char **argv; - // -1 if the grapher is reading from stdin - pid_t pid; - }; +// arguments and script for a stap process +struct StapProcess +{ + StapProcess(pid_t pid_ = -1) : argv(0), pid(pid_) {} + std::string stapArgs; + std::string script; + std::string scriptArgs; + // arguments passed from a single array, like from the command line. + char **argv; + // -1 if the grapher is reading from stdin + pid_t pid; +}; - class StapParser +class StapParser +{ + std::string _buffer; + typedef std::map<std::string, std::tr1::shared_ptr<GraphDataBase> > DataMap; + DataMap _dataSets; + CSVData _csv; + int _errFd; + int _inFd; + unsigned char _lineEndChar; + bool _catchHUP; + std::tr1::shared_ptr<StapProcess> _process; + sigc::connection _ioConnection; + sigc::connection _errIoConnection; +public: + StapParser() + : _errFd(-1), _inFd(-1), _lineEndChar('\n'), _catchHUP(false) + { + } + void parseData(std::tr1::shared_ptr<GraphDataBase> gdata, + int64_t time, const std::string& dataString); + bool ioCallback(Glib::IOCondition ioCondition); + bool errIoCallback(Glib::IOCondition ioCondition); + int getErrFd() const { return _errFd; } + void setErrFd(int fd) { _errFd = fd; } + int getInFd() const { return _inFd; } + void setInFd(int fd) { _inFd = fd; } + pid_t getPid() const + { + if (_process) + return _process->pid; + else + return -1; + } + std::tr1::shared_ptr<StapProcess> getProcess() { return _process; } + void setProcess(std::tr1::shared_ptr<StapProcess> process) { - std::string _buffer; - typedef std::map<std::string, std::tr1::shared_ptr<GraphDataBase> > DataMap; - DataMap _dataSets; - CSVData _csv; - int _errFd; - int _inFd; - unsigned char _lineEndChar; - bool _catchHUP; - std::tr1::shared_ptr<StapProcess> _process; - sigc::connection _ioConnection; - sigc::connection _errIoConnection; - public: - StapParser() - : _errFd(-1), _inFd(-1), _lineEndChar('\n'), _catchHUP(false) - { - } - void parseData(std::tr1::shared_ptr<GraphDataBase> gdata, - int64_t time, const std::string& dataString); - bool ioCallback(Glib::IOCondition ioCondition); - bool errIoCallback(Glib::IOCondition ioCondition); - int getErrFd() const { return _errFd; } - void setErrFd(int fd) { _errFd = fd; } - int getInFd() const { return _inFd; } - void setInFd(int fd) { _inFd = fd; } - pid_t getPid() const - { - if (_process) - return _process->pid; - else - return -1; - } - std::tr1::shared_ptr<StapProcess> getProcess() { return _process; } - void setProcess(std::tr1::shared_ptr<StapProcess> process) - { - _process = process; - } - void initIo(int inFd, int errFd, bool catchHUP); - void disconnect(); - }; + _process = process; + } + void initIo(int inFd, int errFd, bool catchHUP); + void disconnect(); +}; - sigc::signal<void, pid_t>& childDiedSignal(); +sigc::signal<void, pid_t>& childDiedSignal(); - typedef std::vector<std::tr1::shared_ptr<StapParser> > ParserList; - extern ParserList parsers; +typedef std::vector<std::tr1::shared_ptr<StapParser> > ParserList; +extern ParserList parsers; - sigc::signal<void>& parserListChangedSignal(); +sigc::signal<void>& parserListChangedSignal(); } |