1 /* 2 This file is part of Warzone 2100. 3 Copyright (C) 2020 Warzone 2100 Project 4 5 Warzone 2100 is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 Warzone 2100 is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with Warzone 2100; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /** 20 * @file 21 * Definitions for scroll bar functions. 22 */ 23 24 #ifndef __INCLUDED_LIB_WIDGET_DROPDOWN_H__ 25 #define __INCLUDED_LIB_WIDGET_DROPDOWN_H__ 26 27 #include <optional-lite/optional.hpp> 28 #include "widget.h" 29 #include "scrollablelist.h" 30 31 class DropdownItemWrapper; 32 typedef std::function<void(std::shared_ptr<DropdownItemWrapper> item)> DropdownOnSelectHandler; 33 34 class DropdownItemWrapper: public WIDGET 35 { 36 protected: DropdownItemWrapper()37 DropdownItemWrapper() {} 38 39 void initialize(const std::shared_ptr<WIDGET> &newItem, DropdownOnSelectHandler newOnSelect); 40 41 public: make(const std::shared_ptr<WIDGET> & item,DropdownOnSelectHandler onSelect)42 static std::shared_ptr<DropdownItemWrapper> make(const std::shared_ptr<WIDGET> &item, DropdownOnSelectHandler onSelect) 43 { 44 class make_shared_enabler: public DropdownItemWrapper {}; 45 auto widget = std::make_shared<make_shared_enabler>(); 46 widget->initialize(item, onSelect); 47 return widget; 48 } 49 50 bool processClickRecursive(W_CONTEXT *psContext, WIDGET_KEY key, bool wasPressed) override; 51 void geometryChanged() override; 52 getItem()53 const std::shared_ptr<WIDGET>& getItem() const 54 { 55 return item; 56 } 57 setPadding(const Padding & value)58 void setPadding(const Padding &value) 59 { 60 padding = value; 61 } 62 setSelected(bool value)63 void setSelected(bool value) 64 { 65 selected = value; 66 } 67 68 protected: 69 void display(int xOffset, int yOffset) override; 70 71 private: 72 std::shared_ptr<WIDGET> item; 73 DropdownOnSelectHandler onSelect; 74 Padding padding; 75 bool selected = false; 76 }; 77 78 class DropdownWidget : public WIDGET 79 { 80 public: 81 DropdownWidget(); 82 83 void addItem(const std::shared_ptr<WIDGET> &widget); 84 void display(int xOffset, int yOffset) override; 85 void clicked(W_CONTEXT *psContext, WIDGET_KEY key) override; 86 void run(W_CONTEXT *) override; 87 void geometryChanged() override; 88 void open(); 89 void close(); 90 bool processClickRecursive(W_CONTEXT *psContext, WIDGET_KEY key, bool wasPressed) override; setListHeight(uint32_t value)91 void setListHeight(uint32_t value) 92 { 93 itemsList->setGeometry(itemsList->x(), itemsList->y(), itemsList->width(), value); 94 } setItemPadding(const Padding & value)95 void setItemPadding(const Padding &value) 96 { 97 itemPadding = value; 98 } setSelectedIndex(size_t index)99 void setSelectedIndex(size_t index) 100 { 101 ASSERT_OR_RETURN(, index < items.size(), "Invalid dropdown item index"); 102 select(items[index]); 103 } setOnChange(std::function<void (DropdownWidget &)> value)104 void setOnChange(std::function<void(DropdownWidget&)> value) 105 { 106 onChange = value; 107 } getSelectedItem()108 std::shared_ptr<WIDGET> getSelectedItem() const 109 { 110 if (selectedItem == nullptr) 111 { 112 return nullptr; 113 } 114 return selectedItem->getItem(); 115 } getSelectedIndex()116 nonstd::optional<size_t> getSelectedIndex() const 117 { 118 if (selectedItem == nullptr) 119 { 120 return nonstd::nullopt; 121 } 122 123 for (auto item = items.begin(); item != items.end(); item++) 124 { 125 if (*item == selectedItem) 126 { 127 return item - items.begin(); 128 } 129 } 130 131 return nonstd::nullopt; 132 } getScrollbarWidth()133 int getScrollbarWidth() const 134 { 135 ASSERT_OR_RETURN(0, itemsList != nullptr, "null itemsList"); 136 return itemsList->getScrollbarWidth(); 137 } 138 139 private: 140 std::vector<std::shared_ptr<DropdownItemWrapper>> items; 141 std::shared_ptr<ScrollableListWidget> itemsList; 142 std::shared_ptr<W_SCREEN> overlayScreen; 143 std::shared_ptr<DropdownItemWrapper> selectedItem; 144 Padding itemPadding = {0, 0, 0, 0}; 145 std::function<void(DropdownWidget&)> onChange; 146 select(const std::shared_ptr<DropdownItemWrapper> & selected)147 void select(const std::shared_ptr<DropdownItemWrapper> &selected) 148 { 149 if (selectedItem == selected) 150 { 151 return; 152 } 153 154 if (selectedItem) 155 { 156 selectedItem->setSelected(false); 157 } 158 selectedItem = selected; 159 selectedItem->setSelected(true); 160 161 if (onChange) 162 { 163 onChange(*this); 164 } 165 } 166 }; 167 168 #endif // __INCLUDED_LIB_WIDGET_DROPDOWN_H__ 169