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