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 | |