1/*
2 src/combobox.cpp -- simple combo box widget based on a popup button
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/combobox.h>
13#include <nanogui/layout.h>
14#include <nanogui/serializer/core.h>
15#include <cassert>
16
17NAMESPACE_BEGIN(nanogui)
18
19ComboBox::ComboBox(Widget *parent) : PopupButton(parent), mSelectedIndex(0) {
20}
21
22ComboBox::ComboBox(Widget *parent, const std::vector<std::string> &items)
23 : PopupButton(parent), mSelectedIndex(0) {
24 setItems(items);
25}
26
27ComboBox::ComboBox(Widget *parent, const std::vector<std::string> &items, const std::vector<std::string> &itemsShort)
28 : PopupButton(parent), mSelectedIndex(0) {
29 setItems(items, itemsShort);
30}
31
32void ComboBox::setSelectedIndex(int idx) {
33 if (mItemsShort.empty())
34 return;
35 const std::vector<Widget *> &children = popup()->children();
36 ((Button *) children[mSelectedIndex])->setPushed(false);
37 ((Button *) children[idx])->setPushed(true);
38 mSelectedIndex = idx;
39 setCaption(mItemsShort[idx]);
40}
41
42void ComboBox::setItems(const std::vector<std::string> &items, const std::vector<std::string> &itemsShort) {
43 assert(items.size() == itemsShort.size());
44 mItems = items;
45 mItemsShort = itemsShort;
46 if (mSelectedIndex < 0 || mSelectedIndex >= (int) items.size())
47 mSelectedIndex = 0;
48 while (mPopup->childCount() != 0)
49 mPopup->removeChild(mPopup->childCount()-1);
50 mPopup->setLayout(new GroupLayout(10));
51 int index = 0;
52 for (const auto &str: items) {
53 Button *button = new Button(mPopup, str);
54 button->setFlags(Button::RadioButton);
55 button->setCallback([&, index] {
56 mSelectedIndex = index;
57 setCaption(mItemsShort[index]);
58 setPushed(false);
59 popup()->setVisible(false);
60 if (mCallback)
61 mCallback(index);
62 });
63 index++;
64 }
65 setSelectedIndex(mSelectedIndex);
66}
67
68bool ComboBox::scrollEvent(const Vector2i &p, const Vector2f &rel) {
69 if (rel.y() < 0) {
70 setSelectedIndex(std::min(mSelectedIndex+1, (int)(items().size()-1)));
71 if (mCallback)
72 mCallback(mSelectedIndex);
73 return true;
74 } else if (rel.y() > 0) {
75 setSelectedIndex(std::max(mSelectedIndex-1, 0));
76 if (mCallback)
77 mCallback(mSelectedIndex);
78 return true;
79 }
80 return Widget::scrollEvent(p, rel);
81}
82
83void ComboBox::save(Serializer &s) const {
84 Widget::save(s);
85 s.set("items", mItems);
86 s.set("itemsShort", mItemsShort);
87 s.set("selectedIndex", mSelectedIndex);
88}
89
90bool ComboBox::load(Serializer &s) {
91 if (!Widget::load(s)) return false;
92 if (!s.get("items", mItems)) return false;
93 if (!s.get("itemsShort", mItemsShort)) return false;
94 if (!s.get("selectedIndex", mSelectedIndex)) return false;
95 return true;
96}
97
98NAMESPACE_END(nanogui)
99