1 // -*- C++ -*- 2 /* GG is a GUI for OpenGL. 3 Copyright (C) 2003-2008 T. Zachary Laine 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public License 7 as published by the Free Software Foundation; either version 2.1 8 of the License, or (at your option) any later version. 9 10 This library 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 GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA 19 20 If you do not wish to comply with the terms of the LGPL please 21 contact the author as other terms are available for a fee. 22 23 Zach Laine 24 whatwasthataddress@gmail.com */ 25 26 /** \file DropDownList.h \brief Contains the DropDownList class, a control 27 that displays a current selection, and allows the user to select one of 28 several options from a list that drops down when the control is 29 clicked. */ 30 31 #ifndef _GG_DropDownList_h_ 32 #define _GG_DropDownList_h_ 33 34 #include <GG/ListBox.h> 35 #include <GG/GLClientAndServerBuffer.h> 36 37 #include <memory> 38 39 40 class ModalListPicker; 41 42 namespace GG { 43 44 /** \brief Displays a single choice, and allows the user to select items from 45 a drop-down list. 46 47 DropDownList is similar to GG::ListBox, but has significant restrictions 48 over the functionality of GG::ListBox. Specifically, all list items must 49 have the same height, and there is no dragging or dropping. Though any 50 Control-derived object may be placed in an item cell, the items are only 51 interactive in the drop-down list; the currently selected item is 52 displayed only. Most of the ListBox interface is duplicated in 53 DropDownList. Though you can still set the alignment, etc. of individual 54 rows, as in ListBox, the currently-selected row will have the same 55 alignment, etc. when displayed in the control in its unopened state. Note 56 that this may look quite ugly. 57 58 On selection DropDownList emits one of two signals, SelChangedSignal or 59 SelChangedWhileDroppedSignal. SelChangedWhileDroppedSignal is emitted 60 when the selection changes while running a modal event loop to display the 61 drop down list and handle its events. 62 63 SelChangedSignal will also be emitted when the drop down list closes if 64 the selected item changed. 65 */ 66 class GG_API DropDownList : public Control 67 { 68 public: 69 /** This is a single item in a dropdown list. \see See GG::ListBox for details.*/ 70 typedef ListBox::Row Row; 71 72 typedef ListBox::iterator iterator; 73 typedef ListBox::const_iterator const_iterator; 74 75 /** \name Signal Types */ ///@{ 76 /** emitted when a new item is selected; will be end() when no item is 77 * selected */ 78 typedef boost::signals2::signal<void (iterator)> SelChangedSignalType; 79 80 /** Signal \a true when drop down opens and false when it closes.*/ 81 typedef boost::signals2::signal<void (bool)> DropDownOpenedSignalType; 82 //@} 83 84 /** \name Structors */ ///@{ 85 /** basic ctor. DropDownList retains ownership of \a lb, if it is non-null. */ 86 DropDownList(size_t num_shown_elements, Clr color); 87 ~DropDownList(); 88 //@} 89 90 /** \name Accessors */ ///@{ 91 iterator CurrentItem() const; ///< returns the currently selected list item (returns end() if none is selected) 92 std::size_t CurrentItemIndex() const; ///< returns the position of the currently selected list item within the list (returns -1 if none is selected) 93 94 std::size_t IteratorToIndex(iterator it) const; ///< returns the position of \a it within the list (returns -1 if \a it == end()) 95 iterator IndexToIterator(std::size_t n) const; ///< returns an iterator to the row in position \a n (returns end() if \a n is an invalid index) 96 97 bool Empty() const; ///< returns true when the list is empty 98 99 const_iterator begin() const; ///< returns an iterator to the first list row 100 const_iterator end() const; ///< returns an iterator to the imaginary row one past the last 101 102 const Row& GetRow(std::size_t n) const; ///< returns a const reference to the row at index \a n; not range-checked. \note This function is O(n). 103 bool Selected(iterator it) const; ///< returns true if row \a it is selected 104 bool Selected(std::size_t n) const; ///< returns true if row at position \a n is selected 105 Clr InteriorColor() const; ///< returns the color painted into the client area of the control 106 107 Y DropHeight() const; ///< returns the height of the drop-down list 108 bool Dropped() const; ///< Return true if the drop down list is open. 109 110 /** Returns the style flags of the list \see GG::ListBoxStyle */ 111 Flags<ListBoxStyle> Style() const; 112 113 std::size_t NumRows() const; ///< returns the total number of items in the list 114 std::size_t NumCols() const; ///< returns the total number of columns in each list item 115 116 /** Returns the index of the column used to sort items, when sorting is 117 enabled. \note The sort column is not range checked when it is set by 118 the user; it may be >= NumCols(). */ 119 std::size_t SortCol() const; 120 121 X ColWidth(std::size_t n) const; ///< returns the width of column \a n in pixels; not range-checked 122 Alignment ColAlignment(std::size_t n) const; ///< returns the alignment of column \a n; must be LIST_LEFT, LIST_CENTER, or LIST_RIGHT; not range-checked 123 Alignment RowAlignment(iterator it) const; ///< returns the alignment of row \a n; must be LIST_TOP, LIST_VCENTER, or LIST_BOTTOM; not range-checked 124 125 Pt ClientUpperLeft() const override; 126 Pt ClientLowerRight() const override; 127 128 /** Return the width of the displayed row. Override this function if the displayed row is a 129 different width than the client width.*/ 130 virtual GG::X DisplayedRowWidth() const; 131 132 /** Return the width of the dropped row. Override this function if the dropped row is a 133 different width than the client width.*/ 134 virtual GG::X DroppedRowWidth() const; 135 136 /** The selection change signal while not running the modal drop down box. 137 This will also signal an event when the drop list closes if the selection changed. 138 */ 139 mutable SelChangedSignalType SelChangedSignal; 140 /** The selection change signal while running the modal drop down box.*/ 141 mutable SelChangedSignalType SelChangedWhileDroppedSignal; 142 143 DropDownOpenedSignalType DropDownOpenedSignal; 144 //@} 145 146 /** \name Mutators */ ///@{ 147 void PreRender() override; 148 void Render() override; 149 /** Resizes the control, ensuring the proper height is maintained based on 150 the list's row height. */ 151 void SizeMove(const Pt& ul, const Pt& lr) override; 152 void SetColor(Clr c) override; 153 154 /** Insertion sorts \a row into a sorted list, or inserts into an unsorted 155 list before \a it; returns index of insertion point. This Row becomes 156 the property of the DropDownList and should not be deleted or inserted 157 into any other DropDownLists */ 158 iterator Insert(std::shared_ptr<Row> row, iterator it); 159 160 /** Insertion sorts \a row into a sorted list, or inserts into an unsorted 161 list at the end of the list; returns index of insertion point. This 162 Row becomes the property of the DropDownList and should not be deleted 163 or inserted into any other DropDownLists */ 164 iterator Insert(std::shared_ptr<Row> row); 165 166 /** Insertion sorts \a rows into a sorted list, or inserts into an unsorted 167 list before \a it. The Rows become the property of this DropDownList. */ 168 void Insert(const std::vector<std::shared_ptr<Row>>& rows, iterator it); 169 170 /** Insertion sorts \a rows into sorted list, or inserts into an unsorted 171 list at the end of the list. The Rows become the property of thiis 172 DropDownList. */ 173 void Insert(const std::vector<std::shared_ptr<Row>>& rows); 174 175 std::shared_ptr<Row> Erase(iterator it, bool signal = false); ///< removes and returns \a it from the list, or 0 if no such row exists 176 void Clear(); ///< empties the list 177 178 iterator begin(); ///< returns an iterator to the first list row 179 iterator end(); ///< returns an iterator to the imaginary row one past the last one 180 181 Row& GetRow(std::size_t n); ///< returns a reference to the Row at row index \a n; not range-checked. \note This function is O(n). 182 183 void Select(iterator it); ///< selects row-item \a it in the list 184 void Select(std::size_t n); ///< selects row-item \a it in the list 185 186 void SetInteriorColor(Clr c); ///< sets the color painted into the client area of the control 187 188 /** sets the style flags for the list to \a s (invalidates currently 189 selected item). \see GG::ListBoxStyle */ 190 void SetStyle(Flags<ListBoxStyle> s); 191 192 void SetNumCols(std::size_t n); ///< sets the number of columns in each list item to \a n; if no column widths exist before this call, proportional widths are calulated and set, otherwise no column widths are set 193 void SetSortCol(std::size_t n); ///< sets the index of the column used to sort rows when sorting is enabled (invalidates currently selected item); not range-checked 194 void SetColWidth(std::size_t n, X w);///< sets the width of column \n to \a w; not range-checked 195 196 /** Fixes the column widths; by default, an empty list will take on the 197 number of columns of its first added row. \note The number of columns 198 and their widths may still be set via SetNumCols() and SetColWidth() 199 after this function has been called. */ 200 void LockColWidths(); 201 202 /** Allows the number of columns to be determined by the first row added 203 to an empty ListBox */ 204 void UnLockColWidths(); 205 206 /** Set ListBox to stop managing column widths and alignment. The number of columns must be 207 set with SetColWidth(), but widths of individual rows columns or the header will not be 208 managed by ListBox. */ 209 void ManuallyManageColProps(); 210 211 void SetColAlignment(std::size_t n, Alignment align); ///< sets the alignment of column \a n to \a align; not range-checked 212 void SetRowAlignment(iterator it, Alignment align); ///< sets the alignment of the Row at row index \a n to \a align; not range-checked 213 214 /** Sets the stretch of column \a n to \a stretch; not range-checked */ 215 void SetColStretch(std::size_t n, double stretch); 216 217 /** Sets whether to normalize rows when inserted (true) or leave them as 218 * they are. */ 219 void NormalizeRowsOnInsert(bool enable = true); 220 221 /** Set the drop down list to only mouse scroll if it is dropped. */ 222 void SetOnlyMouseScrollWhenDropped(bool enable); 223 //@} 224 225 protected: 226 /** \name Mutators */ ///@{ 227 void LButtonDown(const Pt& pt, Flags<ModKey> mod_keys) override; 228 void KeyPress(Key key, std::uint32_t key_code_point, Flags<ModKey> mod_keys) override; 229 void MouseWheel(const Pt& pt, int move, Flags<ModKey> mod_keys) override; 230 231 ListBox* LB(); ///< returns the ListBox used to render the selected row and the popup list 232 233 virtual void InitBuffer(); 234 virtual void RenderDisplayedRow(); 235 236 GL2DVertexBuffer m_buffer; 237 //@} 238 239 private: 240 const ListBox* LB() const; 241 242 const std::shared_ptr<ModalListPicker> m_modal_picker; 243 }; 244 245 } // namespace GG 246 247 #endif 248