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