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 | |
17 | NAMESPACE_BEGIN(nanogui) |
18 | |
19 | ComboBox::ComboBox(Widget *parent) : PopupButton(parent), mSelectedIndex(0) { |
20 | } |
21 | |
22 | ComboBox::ComboBox(Widget *parent, const std::vector<std::string> &items) |
23 | : PopupButton(parent), mSelectedIndex(0) { |
24 | setItems(items); |
25 | } |
26 | |
27 | ComboBox::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 | |
32 | void 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 | |
42 | void 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 | |
68 | bool 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 | |
83 | void 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 | |
90 | bool 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 | |
98 | NAMESPACE_END(nanogui) |
99 | |