| 1 | /* |
| 2 | src/graph.cpp -- Simple graph widget for showing a function plot |
| 3 | |
| 4 | NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>. |
| 5 | The widget drawing code is based on the NanoVG demo application |
| 6 | by Mikko Mononen. |
| 7 | |
| 8 | All rights reserved. Use of this source code is governed by a |
| 9 | BSD-style license that can be found in the LICENSE.txt file. |
| 10 | */ |
| 11 | |
| 12 | #include <nanogui/graph.h> |
| 13 | #include <nanogui/theme.h> |
| 14 | #include <nanogui/opengl.h> |
| 15 | #include <nanogui/serializer/core.h> |
| 16 | |
| 17 | NAMESPACE_BEGIN(nanogui) |
| 18 | |
| 19 | Graph::Graph(Widget *parent, const std::string &caption) |
| 20 | : Widget(parent), mCaption(caption) { |
| 21 | mBackgroundColor = Color(20, 128); |
| 22 | mForegroundColor = Color(255, 192, 0, 128); |
| 23 | mTextColor = Color(240, 192); |
| 24 | } |
| 25 | |
| 26 | Vector2i Graph::preferredSize(NVGcontext *) const { |
| 27 | return Vector2i(180, 45); |
| 28 | } |
| 29 | |
| 30 | void Graph::draw(NVGcontext *ctx) { |
| 31 | Widget::draw(ctx); |
| 32 | |
| 33 | nvgBeginPath(ctx); |
| 34 | nvgRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y()); |
| 35 | nvgFillColor(ctx, mBackgroundColor); |
| 36 | nvgFill(ctx); |
| 37 | |
| 38 | if (mValues.size() < 2) |
| 39 | return; |
| 40 | |
| 41 | nvgBeginPath(ctx); |
| 42 | nvgMoveTo(ctx, mPos.x(), mPos.y()+mSize.y()); |
| 43 | for (size_t i = 0; i < (size_t) mValues.size(); i++) { |
| 44 | float value = mValues[i]; |
| 45 | float vx = mPos.x() + i * mSize.x() / (float) (mValues.size() - 1); |
| 46 | float vy = mPos.y() + (1-value) * mSize.y(); |
| 47 | nvgLineTo(ctx, vx, vy); |
| 48 | } |
| 49 | |
| 50 | nvgLineTo(ctx, mPos.x() + mSize.x(), mPos.y() + mSize.y()); |
| 51 | nvgStrokeColor(ctx, Color(100, 255)); |
| 52 | nvgStroke(ctx); |
| 53 | nvgFillColor(ctx, mForegroundColor); |
| 54 | nvgFill(ctx); |
| 55 | |
| 56 | nvgFontFace(ctx, "sans" ); |
| 57 | |
| 58 | if (!mCaption.empty()) { |
| 59 | nvgFontSize(ctx, 14.0f); |
| 60 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); |
| 61 | nvgFillColor(ctx, mTextColor); |
| 62 | nvgText(ctx, mPos.x() + 3, mPos.y() + 1, mCaption.c_str(), NULL); |
| 63 | } |
| 64 | |
| 65 | if (!mHeader.empty()) { |
| 66 | nvgFontSize(ctx, 18.0f); |
| 67 | nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); |
| 68 | nvgFillColor(ctx, mTextColor); |
| 69 | nvgText(ctx, mPos.x() + mSize.x() - 3, mPos.y() + 1, mHeader.c_str(), NULL); |
| 70 | } |
| 71 | |
| 72 | if (!mFooter.empty()) { |
| 73 | nvgFontSize(ctx, 15.0f); |
| 74 | nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); |
| 75 | nvgFillColor(ctx, mTextColor); |
| 76 | nvgText(ctx, mPos.x() + mSize.x() - 3, mPos.y() + mSize.y() - 1, mFooter.c_str(), NULL); |
| 77 | } |
| 78 | |
| 79 | nvgBeginPath(ctx); |
| 80 | nvgRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y()); |
| 81 | nvgStrokeColor(ctx, Color(100, 255)); |
| 82 | nvgStroke(ctx); |
| 83 | } |
| 84 | |
| 85 | void Graph::save(Serializer &s) const { |
| 86 | Widget::save(s); |
| 87 | s.set("caption" , mCaption); |
| 88 | s.set("header" , mHeader); |
| 89 | s.set("footer" , mFooter); |
| 90 | s.set("backgroundColor" , mBackgroundColor); |
| 91 | s.set("foregroundColor" , mForegroundColor); |
| 92 | s.set("textColor" , mTextColor); |
| 93 | s.set("values" , mValues); |
| 94 | } |
| 95 | |
| 96 | bool Graph::load(Serializer &s) { |
| 97 | if (!Widget::load(s)) return false; |
| 98 | if (!s.get("caption" , mCaption)) return false; |
| 99 | if (!s.get("header" , mHeader)) return false; |
| 100 | if (!s.get("footer" , mFooter)) return false; |
| 101 | if (!s.get("backgroundColor" , mBackgroundColor)) return false; |
| 102 | if (!s.get("foregroundColor" , mForegroundColor)) return false; |
| 103 | if (!s.get("textColor" , mTextColor)) return false; |
| 104 | if (!s.get("values" , mValues)) return false; |
| 105 | return true; |
| 106 | } |
| 107 | |
| 108 | NAMESPACE_END(nanogui) |
| 109 | |