MyGUI 3.4.3
MyGUI_ComboBox.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
8#include "MyGUI_ComboBox.h"
10#include "MyGUI_InputManager.h"
11#include "MyGUI_WidgetManager.h"
12#include "MyGUI_Gui.h"
13#include "MyGUI_ListBox.h"
14#include "MyGUI_Button.h"
15#include "MyGUI_ResourceSkin.h"
16#include "MyGUI_LayerManager.h"
18
19namespace MyGUI
20{
21
24 const float COMBO_ALPHA_COEF = 4.0f;
25
27 {
29
31 assignWidget(mButton, "Button");
32 if (mButton != nullptr)
33 {
34 mButton->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyButtonPressed);
35 }
36
38 assignWidget(mList, "List");
39
40 if (mList == nullptr)
41 {
42 std::string_view list_skin = getUserString("ListSkin");
43 std::string_view list_layer = getUserString("ListLayer");
44
45 mList = static_cast<ListBox*>(_createSkinWidget(
48 list_skin,
49 IntCoord(),
51 list_layer));
52 }
53
54 if (mList != nullptr)
55 {
56 mList->setActivateOnClick(true);
57
58 mList->setVisible(false);
59 mList->eventKeyLostFocus += newDelegate(this, &ComboBox::notifyListLostFocus);
60 mList->eventListSelectAccept += newDelegate(this, &ComboBox::notifyListSelectAccept);
61 mList->eventListMouseItemActivate += newDelegate(this, &ComboBox::notifyListMouseItemActivate);
62 mList->eventListChangePosition += newDelegate(this, &ComboBox::notifyListChangePosition);
63
64 mList->setNeedToolTip(true);
65 mList->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip);
66 }
67
68 // подписываем дочерние классы на скролл
69 if (mScrollViewClient != nullptr)
70 {
71 mScrollViewClient->eventMouseWheel += newDelegate(this, &ComboBox::notifyMouseWheel);
72 mScrollViewClient->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyMousePressed);
73
74 mScrollViewClient->setNeedToolTip(true);
75 mScrollViewClient->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip);
76 }
77
78 // подписываемся на изменения текста
79 eventEditTextChange += newDelegate(this, &ComboBox::notifyEditTextChange);
80 }
81
83 {
84 mList = nullptr;
85 mButton = nullptr;
86
88 }
89
90 void ComboBox::notifyButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
91 {
92 if (MouseButton::Left != _id)
93 return;
94
95 mDropMouse = true;
96
97 if (mListShow)
98 hideList();
99 else
100 showList();
101 }
102
103 void ComboBox::notifyListLostFocus(Widget* _sender, Widget* _new)
104 {
105 if (mDropMouse)
106 {
107 mDropMouse = false;
109
110 // кнопка сама уберет список
111 if (focus == mButton)
112 return;
113
114 // в режиме дропа все окна учавствуют
115 if (mModeDrop && focus == mScrollViewClient)
116 return;
117 }
118
119 hideList();
120 }
121
122 void ComboBox::notifyListSelectAccept(ListBox* _widget, size_t _position)
123 {
124 mItemIndex = _position;
125 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : UString());
126
127 mDropMouse = false;
129
130 if (mModeDrop)
131 {
132 _resetContainer(false);
133
134 eventComboAccept(this, mItemIndex);
135 }
136 }
137
138 void ComboBox::notifyListChangePosition(ListBox* _widget, size_t _position)
139 {
140 mItemIndex = _position;
141
142 _resetContainer(false);
143
144 eventComboChangePosition(this, _position);
145 }
146
148 {
149 Base::onKeyButtonPressed(_key, _char);
150
151 // при нажатии вниз, показываем лист
152 if (_key == KeyCode::ArrowDown)
153 {
154 // выкидываем список только если мыша свободна
155 if (!InputManager::getInstance().isCaptureMouse())
156 {
157 showList();
158 }
159 }
160 // нажат ввод в окне редиктирования
161 else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter))
162 {
163 _resetContainer(false);
164
165 eventComboAccept(this, mItemIndex);
166 }
167 }
168
169 void ComboBox::notifyListMouseItemActivate(ListBox* _widget, size_t _position)
170 {
171 mItemIndex = _position;
172 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : UString());
173
175
176 if (mModeDrop)
177 {
178 _resetContainer(false);
179
180 eventComboAccept(this, mItemIndex);
181 }
182 }
183
184 void ComboBox::notifyMouseWheel(Widget* _sender, int _rel)
185 {
186 if (mList->getItemCount() == 0)
187 return;
188 if (InputManager::getInstance().getKeyFocusWidget() != this)
189 return;
190 if (InputManager::getInstance().isCaptureMouse())
191 return;
192
193 if (_rel > 0)
194 {
195 if (mItemIndex != 0)
196 {
197 if (mItemIndex == ITEM_NONE)
198 mItemIndex = 0;
199 else
200 mItemIndex--;
201 Base::setCaption(mList->getItemNameAt(mItemIndex));
202 mList->setIndexSelected(mItemIndex);
203 mList->beginToItemAt(mItemIndex);
204
205 _resetContainer(false);
206
207 eventComboChangePosition(this, mItemIndex);
208 }
209 }
210 else if (_rel < 0)
211 {
212 if ((mItemIndex + 1) < mList->getItemCount())
213 {
214 if (mItemIndex == ITEM_NONE)
215 mItemIndex = 0;
216 else
217 mItemIndex++;
218 Base::setCaption(mList->getItemNameAt(mItemIndex));
219 mList->setIndexSelected(mItemIndex);
220 mList->beginToItemAt(mItemIndex);
221
222 _resetContainer(false);
223
224 eventComboChangePosition(this, mItemIndex);
225 }
226 }
227 }
228
229 void ComboBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
230 {
231 // обязательно отдаем отцу, а то мы у него в наглую отняли
232 Base::notifyMousePressed(_sender, _left, _top, _id);
233
234 mDropMouse = true;
235
236 // показываем список
237 if (mModeDrop)
238 notifyButtonPressed(nullptr, _left, _top, _id);
239 }
240
241 void ComboBox::notifyEditTextChange(EditBox* _sender)
242 {
243 // сбрасываем выделенный элемент
244 if (ITEM_NONE != mItemIndex)
245 {
246 mItemIndex = ITEM_NONE;
247 mList->setIndexSelected(mItemIndex);
248 mList->beginToItemFirst();
249
250 _resetContainer(false);
251
252 eventComboChangePosition(this, mItemIndex);
253 }
254 }
255
256 void ComboBox::showList()
257 {
258 // пустой список не показываем
259 if (mList->getItemCount() == 0)
260 return;
261
262 if (mListShow)
263 return;
264 mListShow = true;
265
266 IntCoord coord = calculateListPosition();
267 mList->setCoord(coord);
268
269 if (mShowSmooth)
270 {
271 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MAX, COMBO_ALPHA_COEF, true);
272 ControllerManager::getInstance().addItem(mList, controller);
273 }
274 else
275 {
276 mList->setVisible(true);
277 }
278
280 }
281
282 void ComboBox::actionWidgetHide(Widget* _widget, ControllerItem* _controller)
283 {
284 _widget->setVisible(false);
285 _widget->setEnabled(true);
286 }
287
288 void ComboBox::hideList()
289 {
290 if (!mListShow)
291 return;
292 mListShow = false;
293
294 if (mShowSmooth)
295 {
296 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MIN, COMBO_ALPHA_COEF, false);
297 controller->eventPostAction += newDelegate(this, &ComboBox::actionWidgetHide);
298 ControllerManager::getInstance().addItem(mList, controller);
299 }
300 else
301 {
302 mList->setVisible(false);
303 }
304 }
305
306 void ComboBox::setIndexSelected(size_t _index)
307 {
308 MYGUI_ASSERT_RANGE_AND_NONE(_index, mList->getItemCount(), "ComboBox::setIndexSelected");
309 mItemIndex = _index;
310 mList->setIndexSelected(_index);
311 if (_index == ITEM_NONE)
312 {
314 return;
315 }
316 Base::setCaption(mList->getItemNameAt(_index));
317 Base::updateView(); // hook for update
318 }
319
320 void ComboBox::setItemNameAt(size_t _index, const UString& _name)
321 {
322 mList->setItemNameAt(_index, _name);
323 mItemIndex = ITEM_NONE; //FIXME
324 mList->setIndexSelected(mItemIndex); //FIXME
325 }
326
327 void ComboBox::setItemDataAt(size_t _index, Any _data)
328 {
329 mList->setItemDataAt(_index, _data);
330 mItemIndex = ITEM_NONE; //FIXME
331 mList->setIndexSelected(mItemIndex); //FIXME
332 }
333
334 void ComboBox::insertItemAt(size_t _index, const UString& _item, Any _data)
335 {
336 mList->insertItemAt(_index, _item, _data);
337 mItemIndex = ITEM_NONE; //FIXME
338 mList->setIndexSelected(mItemIndex); //FIXME
339 }
340
341 void ComboBox::removeItemAt(size_t _index)
342 {
343 mList->removeItemAt(_index);
344 mItemIndex = ITEM_NONE; //FIXME
345 mList->clearIndexSelected(); //FIXME
346 }
347
349 {
350 mItemIndex = ITEM_NONE; //FIXME
351 mList->removeAllItems(); //FIXME заново созданные строки криво стоят
352 }
353
355 {
356 mModeDrop = _drop;
357 setEditStatic(mModeDrop);
358 }
359
360 ControllerFadeAlpha* ComboBox::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
361 {
363 ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
364
365 controller->setAlpha(_alpha);
366 controller->setCoef(_coef);
367 controller->setEnabled(_enable);
368
369 return controller;
370 }
371
373 {
374 return mList->findItemIndexWith(_name);
375 }
376
378 {
379 mFlowDirection = _value;
380 }
381
382 IntCoord ComboBox::calculateListPosition()
383 {
384 int length = 0;
385 if (mFlowDirection.isVertical())
386 length = mList->getOptimalHeight();
387 else
388 length = mMaxListLength;
389
390 if (mMaxListLength > 0 && length > mMaxListLength)
391 length = mMaxListLength;
392
393 // берем глобальные координаты выджета
394 IntCoord coord = getAbsoluteCoord();
395 // размер леера
396 IntSize sizeView = mList->getParentSize();
397
398 if (mFlowDirection == FlowDirection::TopToBottom)
399 {
400 if ((coord.bottom() + length) <= sizeView.height)
401 coord.top += coord.height;
402 else
403 coord.top -= length;
404 coord.height = length;
405 }
406 else if (mFlowDirection == FlowDirection::BottomToTop)
407 {
408 if ((coord.top - length) >= 0)
409 coord.top -= length;
410 else
411 coord.top += coord.height;
412 coord.height = length;
413 }
414 else if (mFlowDirection == FlowDirection::LeftToRight)
415 {
416 if ((coord.right() + length) <= sizeView.width)
417 coord.left += coord.width;
418 else
419 coord.left -= length;
420 coord.width = length;
421 }
422 else if (mFlowDirection == FlowDirection::RightToLeft)
423 {
424 if ((coord.left - length) >= 0)
425 coord.left -= length;
426 else
427 coord.left += coord.width;
428 coord.width = length;
429 }
430
431 return coord;
432 }
433
434 void ComboBox::setPropertyOverride(std::string_view _key, std::string_view _value)
435 {
437 if (_key == "ModeDrop")
439
441 else if (_key == "FlowDirection")
443
445 else if (_key == "MaxListLength")
447
449 else if (_key == "SmoothShow")
451
452 // не коментировать
453 else if (_key == "AddItem")
454 addItem(LanguageManager::getInstance().replaceTags(UString(_value)));
455
456 else
457 {
458 Base::setPropertyOverride(_key, _value);
459 return;
460 }
461
462 eventChangeProperty(this, _key, _value);
463 }
464
466 {
467 return mList->getItemCount();
468 }
469
470 void ComboBox::addItem(const UString& _name, Any _data)
471 {
472 return insertItemAt(ITEM_NONE, _name, _data);
473 }
474
476 {
477 return mItemIndex;
478 }
479
484
485 void ComboBox::clearItemDataAt(size_t _index)
486 {
487 setItemDataAt(_index, Any::Null);
488 }
489
490 const UString& ComboBox::getItemNameAt(size_t _index) const
491 {
492 return mList->getItemNameAt(_index);
493 }
494
495 void ComboBox::beginToItemAt(size_t _index)
496 {
497 mList->beginToItemAt(_index);
498 }
499
501 {
502 if (getItemCount())
503 beginToItemAt(0);
504 }
505
507 {
508 if (getItemCount())
510 }
511
517
519 {
520 return mModeDrop;
521 }
522
523 void ComboBox::setSmoothShow(bool _value)
524 {
525 mShowSmooth = _value;
526 }
527
529 {
530 return mShowSmooth;
531 }
532
534 {
535 mMaxListLength = _value;
536 }
537
539 {
540 return mMaxListLength;
541 }
542
544 {
545 return mFlowDirection;
546 }
547
548 void ComboBox::notifyToolTip(Widget* _sender, const ToolTipInfo& _info)
549 {
550 if (getNeedToolTip())
551 eventToolTip(this, _info);
552 }
553
555 {
556 return getItemCount();
557 }
558
560 {
561 addItem(_name);
562 }
563
564 void ComboBox::_removeItemAt(size_t _index)
565 {
566 removeItemAt(_index);
567 }
568
569 void ComboBox::_setItemNameAt(size_t _index, const UString& _name)
570 {
571 setItemNameAt(_index, _name);
572 }
573
574 const UString& ComboBox::_getItemNameAt(size_t _index) const
575 {
576 return getItemNameAt(_index);
577 }
578
579 void ComboBox::_resetContainer(bool _update)
580 {
581 Base::_resetContainer(_update);
582 if (mList != nullptr)
583 mList->_resetContainer(_update);
584 }
585
586} // namespace MyGUI
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
static const Any Null
Definition MyGUI_Any.h:58
void addItem(const UString &_name, Any _data=Any::Null)
Add an item to the end of a array.
void beginToItemSelected()
Move all elements so selected becomes visible.
EventPairAddParameter< EventHandle_WidgetVoid, EventHandle_ComboBoxPtrSizeT > eventComboAccept
size_t findItemIndexWith(const UString &_name)
Search item, returns the position of the first occurrence in array or ITEM_NONE if item not found.
void _setItemNameAt(size_t _index, const UString &_name) override
void clearIndexSelected()
Clear item selection.
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name at a specified position.
void setIndexSelected(size_t _index)
Select specified _index.
void removeAllItems()
Remove all items.
void _addItem(const MyGUI::UString &_name) override
void onKeyButtonPressed(KeyCode _key, Char _char) override
const UString & _getItemNameAt(size_t _index) const override
void _removeItemAt(size_t _index) override
void shutdownOverride() override
void insertItemAt(size_t _index, const UString &_item, Any _data=Any::Null)
Insert an item into a array at a specified position.
size_t getIndexSelected() const
Get index of selected item (ITEM_NONE if none selected)
void beginToItemAt(size_t _index)
Move all elements so specified becomes visible.
bool getSmoothShow() const
Get smooth show of list flag.
void setFlowDirection(FlowDirection _value)
Set direction, where drop down list appears (TopToBottom by default).
void beginToItemLast()
Move all elements so last becomes visible.
void setMaxListLength(int _value)
Get max list length.
void initialiseOverride() override
bool getComboModeDrop() const
Get drop list mode flag.
EventPair< EventHandle_WidgetSizeT, EventHandle_ComboBoxPtrSizeT > eventComboChangePosition
void setSmoothShow(bool _value)
Set smooth show of list.
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
size_t _getItemCount() const override
void removeItemAt(size_t _index)
Remove item at a specified position.
void clearItemDataAt(size_t _index)
Clear an item data at a specified position.
void _resetContainer(bool _update) override
int getMaxListLength() const
Set max list length.
void beginToItemFirst()
Move all elements so first becomes visible.
size_t getItemCount() const
Get number of items.
FlowDirection getFlowDirection() const
Get direction, where drop down list appears.
void setPropertyOverride(std::string_view _key, std::string_view _value) override
const UString & getItemNameAt(size_t _index) const
Get item name from specified position.
void setComboModeDrop(bool _drop)
Set drop list mode (text can not be edited)
static std::string_view getClassTypeName()
ControllerItem * createItem(std::string_view _type)
static ControllerManager & getInstance()
void addItem(Widget *_widget, ControllerItem *_item)
widget description should be here.
void setEditStatic(bool _value)
EventPair< EventHandle_WidgetVoid, EventHandle_EditPtr > eventEditTextChange
void setCaption(const UString &_value) override
Type * castType(bool _throw=true)
void setKeyFocusWidget(Widget *_widget)
Widget * getMouseFocusWidget() const
static InputManager & getInstance()
static LanguageManager & getInstance()
widget description should be here.
static std::string_view getClassTypeName()
const UString & getItemNameAt(size_t _index) const
Get item name from specified position.
int getOptimalHeight() const
Return optimal height to fit all items in ListBox.
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
std::string_view getUserString(std::string_view _key) const
widget description should be here.
EventHandle_WidgetStringString eventChangeProperty
IntSize getParentSize() const
void assignWidget(T *&_widget, std::string_view _name)
Widget * _createSkinWidget(WidgetStyle _style, std::string_view _type, std::string_view _skin, const IntCoord &_coord, Align _align, std::string_view _layer={}, std::string_view _name={})
EventHandle_WidgetToolTip eventToolTip
T parseValue(std::string_view _value)
constexpr float ALPHA_MAX
constexpr float ALPHA_MIN
const float COMBO_ALPHA_MAX
const float COMBO_ALPHA_MIN
unsigned int Char
Definition MyGUI_Types.h:50
constexpr size_t ITEM_NONE
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
types::TSize< int > IntSize
Definition MyGUI_Types.h:30
const float COMBO_ALPHA_COEF
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))