1/*
2 src/checkbox.cpp -- Two-state check box widget
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/checkbox.h>
13#include <nanogui/opengl.h>
14#include <nanogui/theme.h>
15#include <nanogui/serializer/core.h>
16
17NAMESPACE_BEGIN(nanogui)
18
19CheckBox::CheckBox(Widget *parent, const std::string &caption,
20 const std::function<void(bool) > &callback)
21 : Widget(parent), mCaption(caption), mPushed(false), mChecked(false),
22 mCallback(callback) {
23
24 mIconExtraScale = 1.2f;// widget override
25}
26
27bool CheckBox::mouseButtonEvent(const Vector2i &p, int button, bool down,
28 int modifiers) {
29 Widget::mouseButtonEvent(p, button, down, modifiers);
30 if (!mEnabled)
31 return false;
32
33 if (button == GLFW_MOUSE_BUTTON_1) {
34 if (down) {
35 mPushed = true;
36 } else if (mPushed) {
37 if (contains(p)) {
38 mChecked = !mChecked;
39 if (mCallback)
40 mCallback(mChecked);
41 }
42 mPushed = false;
43 }
44 return true;
45 }
46 return false;
47}
48
49Vector2i CheckBox::preferredSize(NVGcontext *ctx) const {
50 if (mFixedSize != Vector2i::Zero())
51 return mFixedSize;
52 nvgFontSize(ctx, fontSize());
53 nvgFontFace(ctx, "sans");
54 return Vector2i(
55 nvgTextBounds(ctx, 0, 0, mCaption.c_str(), nullptr, nullptr) +
56 1.8f * fontSize(),
57 fontSize() * 1.3f);
58}
59
60void CheckBox::draw(NVGcontext *ctx) {
61 Widget::draw(ctx);
62
63 nvgFontSize(ctx, fontSize());
64 nvgFontFace(ctx, "sans");
65 nvgFillColor(ctx,
66 mEnabled ? mTheme->mTextColor : mTheme->mDisabledTextColor);
67 nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
68 nvgText(ctx, mPos.x() + 1.6f * fontSize(), mPos.y() + mSize.y() * 0.5f,
69 mCaption.c_str(), nullptr);
70
71 NVGpaint bg = nvgBoxGradient(ctx, mPos.x() + 1.5f, mPos.y() + 1.5f,
72 mSize.y() - 2.0f, mSize.y() - 2.0f, 3, 3,
73 mPushed ? Color(0, 100) : Color(0, 32),
74 Color(0, 0, 0, 180));
75
76 nvgBeginPath(ctx);
77 nvgRoundedRect(ctx, mPos.x() + 1.0f, mPos.y() + 1.0f, mSize.y() - 2.0f,
78 mSize.y() - 2.0f, 3);
79 nvgFillPaint(ctx, bg);
80 nvgFill(ctx);
81
82 if (mChecked) {
83 nvgFontSize(ctx, mSize.y() * icon_scale());
84 nvgFontFace(ctx, "icons");
85 nvgFillColor(ctx, mEnabled ? mTheme->mIconColor
86 : mTheme->mDisabledTextColor);
87 nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
88 nvgText(ctx, mPos.x() + mSize.y() * 0.5f + 1,
89 mPos.y() + mSize.y() * 0.5f, utf8(mTheme->mCheckBoxIcon).data(),
90 nullptr);
91 }
92}
93
94void CheckBox::save(Serializer &s) const {
95 Widget::save(s);
96 s.set("caption", mCaption);
97 s.set("pushed", mPushed);
98 s.set("checked", mChecked);
99}
100
101bool CheckBox::load(Serializer &s) {
102 if (!Widget::load(s)) return false;
103 if (!s.get("caption", mCaption)) return false;
104 if (!s.get("pushed", mPushed)) return false;
105 if (!s.get("checked", mChecked)) return false;
106 return true;
107}
108
109NAMESPACE_END(nanogui)
110