1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WCOMBOBOX_H_ 8 #define WCOMBOBOX_H_ 9 10 #include <Wt/WFormWidget.h> 11 #include <string> 12 13 namespace Wt { 14 15 /*! \class WComboBox Wt/WComboBox.h Wt/WComboBox.h 16 * \brief A widget that provides a drop-down combo-box control. 17 * 18 * A combo box provides the user with a set of options, from which one 19 * option may be selected. 20 * 21 * %WComboBox is an MVC view class, using a simple string list model 22 * by default. The model may be populated using 23 * addItem(const WString&) or 24 * insertItem(int, const WString&) and the contents can 25 * be cleared through clear(). These methods manipulate the underlying 26 * model(). 27 * 28 * To use the combo box with a custom model instead of the default 29 * WStringListModel, use setModel(). 30 * 31 * To react to selection events, connect to the changed(), activated() 32 * or sactivated() signals. 33 * 34 * At all times, the current selection index is available through 35 * currentIndex() and the current selection text using currentText(). 36 * 37 * WComboBox does not have support for auto-completion, this behaviour 38 * can be found in the WSuggestionPopup. 39 * 40 * \if cpp 41 * Usage example: 42 * \code 43 * Wt::WComboBox *combo = addWidget(std::make_unique<Wt::WComboBox>()); 44 * combo->addItem("Clint Eastwood"); 45 * combo->addItem("Mick Jagger"); 46 * combo->addItem("Johnny Depp"); 47 * combo->addItem("Kate Winslet"); 48 * 49 * combo->setCurrentIndex(2); // Johnny Depp 50 * combo->activated().connect(this, &MyWidget::comboChanged); 51 * \endcode 52 * \endif 53 * 54 * %WComboBox is an \link WWidget::setInline(bool) inline \endlink widget. 55 * 56 * <h3>CSS</h3> 57 * 58 * The widget corresponds to the HTML <tt><select></tt> tag and 59 * does not provide styling. It can be styled using inline or external 60 * CSS as appropriate. 61 * 62 * \ingroup modelview 63 */ 64 class WT_API WComboBox : public WFormWidget 65 { 66 public: 67 /*! \brief Creates an empty combo-box.. 68 */ 69 WComboBox(); 70 71 /*! \brief Adds an option item. 72 * 73 * This adds an item to the underlying model. This requires that the 74 * model() is editable. 75 * 76 * Equivalent to 77 * \link insertItem(int, const WString&) insertItem\endlink (count(), 78 * \p text). 79 */ 80 void addItem(const WString& text); 81 82 /*! \brief Returns the number of items 83 */ 84 int count() const; 85 86 /*! \brief Returns the currently selected item. 87 * 88 * If no item is currently selected, the method returns -1. 89 * 90 * \sa setNoSelectionEnabled() 91 */ 92 int currentIndex() const; 93 94 /*! \brief Inserts an item at the specified position. 95 * 96 * The item is inserted in the underlying model at position 97 * \p index. This requires that the model() is editable. 98 * 99 * \sa addItem(const WString&), removeItem(int) 100 */ 101 void insertItem(int index, const WString& text); 102 103 /*! \brief Removes the item at the specified position. 104 * 105 * The item is removed from the underlying model. This requires that 106 * the model() is editable. 107 * 108 * \sa insertItem(int index, const WString&), clear() 109 */ 110 void removeItem(int index); 111 112 /*! \brief Changes the current selection. 113 * 114 * Specify a value of -1 for \p index to clear the selection. 115 * 116 * \note Setting a value of -1 works only if JavaScript is available. 117 */ 118 void setCurrentIndex(int index); 119 120 /*! \brief Changes the text for a specified option. 121 * 122 * The text for the item at position \p index is changed. This requires 123 * that the model() is editable. 124 */ 125 void setItemText(int index, const WString& text); 126 127 /*! \brief Returns the text of the currently selected item. 128 * 129 * \sa currentIndex(), itemText(int) const 130 */ 131 const WString currentText() const; 132 133 /*! \brief Returns the text of a particular item. 134 * 135 * \sa setItemText(int, const WString&), currentText() 136 */ 137 const WString itemText(int index) const; 138 139 /*! \brief Sets the model to be used for the items. 140 * 141 * The default model is a WStringListModel. 142 * 143 * Items in the model can be grouped by setting the \ref 144 * ItemDataRole::Level. The contents is interpreted by \ref Wt::asString, and 145 * subsequent items of the same group are rendered as children of a 146 * HTML <tt> <optgroup> </tt>element. 147 * 148 * \sa setModelColumn(int) 149 */ 150 void setModel(const std::shared_ptr<WAbstractItemModel> model); 151 152 /*! \brief Sets the column in the model to be used for the items. 153 * 154 * The column \p index in the model will be used to retrieve data. 155 * 156 * The default value is 0. 157 * 158 * \sa setModel() 159 */ 160 void setModelColumn(int index); 161 162 /*! \brief Returns the data model. 163 * 164 * \sa setModel() 165 */ model()166 std::shared_ptr<WAbstractItemModel> model() const { return model_; } 167 168 /*! \brief Returns the index of the first item that matches a text. 169 */ 170 int findText(const WString& text, 171 WFlags<MatchFlag> flags 172 = MatchFlag::Exactly | MatchFlag::CaseSensitive) const; 173 174 /*! \brief Returns the selection mode. 175 * 176 * Always returns SelectionMode::Single for a combo box, but may return 177 * SelectionMode::Extended for a selection box 178 * 179 * \sa WSelectionBox::setSelectionMode() 180 */ selectionMode()181 virtual SelectionMode selectionMode() const { 182 return SelectionMode::Single; 183 } 184 185 /*! \brief Returns the current value. 186 * 187 * \if cpp 188 * Returns currentText(). 189 * \else 190 * Returns currentText() as a String. 191 * \endif 192 */ 193 virtual WT_USTRING valueText() const override; 194 195 /*! \brief Sets the current value. 196 * 197 * Sets the current index to the item corresponding to \p value. 198 */ 199 virtual void setValueText(const WT_USTRING& value) override; 200 201 virtual void refresh() override; 202 203 /*! \brief Clears all items. 204 * 205 * Removes all items from the underlying model. This requires that the 206 * model() is editable. 207 */ 208 void clear(); 209 210 /*! \brief %Signal emitted when the selection changed. 211 * 212 * The newly selected item is passed as an argument. 213 * 214 * \sa sactivated(), currentIndex() 215 */ activated()216 Signal<int>& activated() { return activated_; } 217 218 /*! \brief %Signal emitted when the selection changed. 219 * 220 * The newly selected text is passed as an argument. 221 * 222 * \sa activated(), currentText() 223 */ sactivated()224 Signal<WString>& sactivated() { return sactivated_; } 225 226 /*! \brief Enables the ability to have 'no currently selected' item. 227 * 228 * The setting may only be changed for a combo box (and not for a 229 * selection box). When enabled, the currentIndex() may be '-1' also 230 * when the combo box contains values. The user can however not 231 * select this option, it is thus only useful as a default value. 232 * 233 * By default, no selection is \c false for a combo-box and \c true 234 * for a selection box. 235 */ 236 void setNoSelectionEnabled(bool enabled); 237 238 /*! \brief Returns whether 'no selection' is a valid state. 239 * 240 * \sa setNoSelectionEnabled() 241 */ noSelectionEnabled()242 bool noSelectionEnabled() const { return noSelectionEnabled_; } 243 244 private: 245 std::shared_ptr<WAbstractItemModel> model_; 246 int modelColumn_; 247 int currentIndex_; 248 void *currentIndexRaw_; 249 250 bool itemsChanged_; 251 bool selectionChanged_; 252 bool currentlyConnected_; 253 bool noSelectionEnabled_; 254 255 std::vector<Wt::Signals::connection> modelConnections_; 256 257 Signal<int> activated_; 258 Signal<WString> sactivated_; 259 260 void layoutChanged(); 261 void itemsChanged(); 262 void propagateChange(); 263 264 void rowsInserted(const WModelIndex &index, int from, int to); 265 void rowsRemoved(const WModelIndex &index, int from, int to); 266 void saveSelection(); 267 void restoreSelection(); 268 269 virtual bool supportsNoSelection() const; 270 271 protected: 272 virtual void updateDom(DomElement& element, bool all) override; 273 virtual DomElementType domElementType() const override; 274 virtual void propagateRenderOk(bool deep) override; 275 276 virtual void setFormData(const FormData& formData) override; 277 278 virtual bool isSelected(int index) const; 279 280 friend class WSelectionBox; 281 282 private: 283 void makeCurrentIndexValid(); 284 }; 285 286 } 287 288 #endif // WCOMBOBOX_H_ 289