MyGUI 3.4.2
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 mButton(nullptr),
28 mList(nullptr),
29 mListShow(false),
30 mMaxListLength(-1),
31 mItemIndex(ITEM_NONE),
32 mModeDrop(false),
33 mDropMouse(false),
34 mShowSmooth(false),
35 mFlowDirection(FlowDirection::TopToBottom)
36 {
37 }
38
40 {
42
44 assignWidget(mButton, "Button");
45 if (mButton != nullptr)
46 {
47 mButton->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyButtonPressed);
48 }
49
51 assignWidget(mList, "List");
52
53 if (mList == nullptr)
54 {
55 std::string list_skin = getUserString("ListSkin");
56 std::string list_layer = getUserString("ListLayer");
57
59 }
60
61 if (mList != nullptr)
62 {
63 mList->setActivateOnClick(true);
64
65 mList->setVisible(false);
66 mList->eventKeyLostFocus += newDelegate(this, &ComboBox::notifyListLostFocus);
67 mList->eventListSelectAccept += newDelegate(this, &ComboBox::notifyListSelectAccept);
68 mList->eventListMouseItemActivate += newDelegate(this, &ComboBox::notifyListMouseItemActivate);
69 mList->eventListChangePosition += newDelegate(this, &ComboBox::notifyListChangePosition);
70
71 mList->setNeedToolTip(true);
72 mList->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip);
73 }
74
75 // подписываем дочерние классы на скролл
76 if (mScrollViewClient != nullptr)
77 {
78 mScrollViewClient->eventMouseWheel += newDelegate(this, &ComboBox::notifyMouseWheel);
79 mScrollViewClient->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyMousePressed);
80
82 mScrollViewClient->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip);
83 }
84
85 // подписываемся на изменения текста
86 eventEditTextChange += newDelegate(this, &ComboBox::notifyEditTextChange);
87 }
88
90 {
91 mList = nullptr;
92 mButton = nullptr;
93
95 }
96
97 void ComboBox::notifyButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
98 {
100 return;
101
102 mDropMouse = true;
103
104 if (mListShow)
105 hideList();
106 else
107 showList();
108 }
109
110 void ComboBox::notifyListLostFocus(Widget* _sender, Widget* _new)
111 {
112 if (mDropMouse)
113 {
114 mDropMouse = false;
115 Widget* focus = InputManager::getInstance().getMouseFocusWidget();
116
117 // кнопка сама уберет список
118 if (focus == mButton)
119 return;
120
121 // в режиме дропа все окна учавствуют
122 if (mModeDrop && focus == mScrollViewClient)
123 return;
124 }
125
126 hideList();
127 }
128
129 void ComboBox::notifyListSelectAccept(ListBox* _widget, size_t _position)
130 {
131 mItemIndex = _position;
132 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : "");
133
134 mDropMouse = false;
135 InputManager::getInstance().setKeyFocusWidget(this);
136
137 if (mModeDrop)
138 {
139 _resetContainer(false);
140
142 eventComboAccept.m_event(this, mItemIndex);
143 }
144 }
145
146 void ComboBox::notifyListChangePosition(ListBox* _widget, size_t _position)
147 {
148 mItemIndex = _position;
149
150 _resetContainer(false);
151
152 eventComboChangePosition(this, _position);
153 }
154
156 {
158
159 // при нажатии вниз, показываем лист
161 {
162 // выкидываем список только если мыша свободна
163 if (!InputManager::getInstance().isCaptureMouse())
164 {
165 showList();
166 }
167 }
168 // нажат ввод в окне редиктирования
169 else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter))
170 {
171 _resetContainer(false);
172
174 eventComboAccept.m_event(this, mItemIndex);
175 }
176 }
177
178 void ComboBox::notifyListMouseItemActivate(ListBox* _widget, size_t _position)
179 {
180 mItemIndex = _position;
181 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : "");
182
183 InputManager::getInstance().setKeyFocusWidget(this);
184
185 if (mModeDrop)
186 {
187 _resetContainer(false);
188
190 eventComboAccept.m_event(this, mItemIndex);
191 }
192 }
193
194 void ComboBox::notifyMouseWheel(Widget* _sender, int _rel)
195 {
196 if (mList->getItemCount() == 0)
197 return;
198 if (InputManager::getInstance().getKeyFocusWidget() != this)
199 return;
200 if (InputManager::getInstance().isCaptureMouse())
201 return;
202
203 if (_rel > 0)
204 {
205 if (mItemIndex != 0)
206 {
207 if (mItemIndex == ITEM_NONE)
208 mItemIndex = 0;
209 else
210 mItemIndex --;
211 Base::setCaption(mList->getItemNameAt(mItemIndex));
212 mList->setIndexSelected(mItemIndex);
213 mList->beginToItemAt(mItemIndex);
214
215 _resetContainer(false);
216
217 eventComboChangePosition(this, mItemIndex);
218 }
219 }
220 else if (_rel < 0)
221 {
222 if ((mItemIndex + 1) < mList->getItemCount())
223 {
224 if (mItemIndex == ITEM_NONE)
225 mItemIndex = 0;
226 else
227 mItemIndex ++;
228 Base::setCaption(mList->getItemNameAt(mItemIndex));
229 mList->setIndexSelected(mItemIndex);
230 mList->beginToItemAt(mItemIndex);
231
232 _resetContainer(false);
233
234 eventComboChangePosition(this, mItemIndex);
235 }
236 }
237 }
238
239 void ComboBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
240 {
241 // обязательно отдаем отцу, а то мы у него в наглую отняли
242 Base::notifyMousePressed(_sender, _left, _top, _id);
243
244 mDropMouse = true;
245
246 // показываем список
247 if (mModeDrop)
248 notifyButtonPressed(nullptr, _left, _top, _id);
249 }
250
251 void ComboBox::notifyEditTextChange(EditBox* _sender)
252 {
253 // сбрасываем выделенный элемент
254 if (ITEM_NONE != mItemIndex)
255 {
256 mItemIndex = ITEM_NONE;
257 mList->setIndexSelected(mItemIndex);
258 mList->beginToItemFirst();
259
260 _resetContainer(false);
261
262 eventComboChangePosition(this, mItemIndex);
263 }
264 }
265
266 void ComboBox::showList()
267 {
268 // пустой список не показываем
269 if (mList->getItemCount() == 0)
270 return;
271
272 if (mListShow)
273 return;
274 mListShow = true;
275
276 IntCoord coord = calculateListPosition();
277 mList->setCoord(coord);
278
279 if (mShowSmooth)
280 {
281 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MAX, COMBO_ALPHA_COEF, true);
282 ControllerManager::getInstance().addItem(mList, controller);
283 }
284 else
285 {
286 mList->setVisible(true);
287 }
288
289 InputManager::getInstance().setKeyFocusWidget(mList);
290 }
291
292 void ComboBox::actionWidgetHide(Widget* _widget, ControllerItem* _controller)
293 {
294 _widget->setVisible(false);
295 _widget->setEnabled(true);
296 }
297
298 void ComboBox::hideList()
299 {
300 if (!mListShow)
301 return;
302 mListShow = false;
303
304 if (mShowSmooth)
305 {
306 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MIN, COMBO_ALPHA_COEF, false);
307 controller->eventPostAction += newDelegate(this, &ComboBox::actionWidgetHide);
308 ControllerManager::getInstance().addItem(mList, controller);
309 }
310 else
311 {
312 mList->setVisible(false);
313 }
314 }
315
317 {
318 MYGUI_ASSERT_RANGE_AND_NONE(_index, mList->getItemCount(), "ComboBox::setIndexSelected");
319 mItemIndex = _index;
320 mList->setIndexSelected(_index);
321 if (_index == ITEM_NONE)
322 {
324 return;
325 }
327 Base::updateView(); // hook for update
328 }
329
331 {
332 mList->setItemNameAt(_index, _name);
333 mItemIndex = ITEM_NONE;//FIXME
334 mList->setIndexSelected(mItemIndex);//FIXME
335 }
336
338 {
339 mList->setItemDataAt(_index, _data);
340 mItemIndex = ITEM_NONE;//FIXME
341 mList->setIndexSelected(mItemIndex);//FIXME
342 }
343
345 {
346 mList->insertItemAt(_index, _item, _data);
347 mItemIndex = ITEM_NONE;//FIXME
348 mList->setIndexSelected(mItemIndex);//FIXME
349 }
350
352 {
353 mList->removeItemAt(_index);
354 mItemIndex = ITEM_NONE;//FIXME
355 mList->clearIndexSelected();//FIXME
356 }
357
359 {
360 mItemIndex = ITEM_NONE;//FIXME
361 mList->removeAllItems();//FIXME заново созданные строки криво стоят
362 }
363
365 {
366 mModeDrop = _drop;
367 setEditStatic(mModeDrop);
368 }
369
370 ControllerFadeAlpha* ComboBox::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
371 {
374
375 controller->setAlpha(_alpha);
376 controller->setCoef(_coef);
377 controller->setEnabled(_enable);
378
379 return controller;
380 }
381
383 {
384 return mList->findItemIndexWith(_name);
385 }
386
388 {
389 mFlowDirection = _value;
390 }
391
392 IntCoord ComboBox::calculateListPosition()
393 {
394 int length = 0;
395 if (mFlowDirection.isVertical())
396 length = mList->getOptimalHeight();
397 else
398 length = mMaxListLength;
399
400 if (mMaxListLength > 0 && length > mMaxListLength)
401 length = mMaxListLength;
402
403 // берем глобальные координаты выджета
404 IntCoord coord = getAbsoluteCoord();
405 // размер леера
406 IntSize sizeView = mList->getParentSize();
407
408 if (mFlowDirection == FlowDirection::TopToBottom)
409 {
410 if ((coord.bottom() + length) <= sizeView.height)
411 coord.top += coord.height;
412 else
413 coord.top -= length;
414 coord.height = length;
415 }
416 else if (mFlowDirection == FlowDirection::BottomToTop)
417 {
418 if ((coord.top - length) >= 0)
419 coord.top -= length;
420 else
421 coord.top += coord.height;
422 coord.height = length;
423 }
424 else if (mFlowDirection == FlowDirection::LeftToRight)
425 {
426 if ((coord.right() + length) <= sizeView.width)
427 coord.left += coord.width;
428 else
429 coord.left -= length;
430 coord.width = length;
431 }
432 else if (mFlowDirection == FlowDirection::RightToLeft)
433 {
434 if ((coord.left - length) >= 0)
435 coord.left -= length;
436 else
437 coord.left += coord.width;
438 coord.width = length;
439 }
440
441 return coord;
442 }
443
444 void ComboBox::setPropertyOverride(const std::string& _key, const std::string& _value)
445 {
447 if (_key == "ModeDrop")
448 setComboModeDrop(utility::parseValue<bool>(_value));
449
451 else if (_key == "FlowDirection")
452 setFlowDirection(utility::parseValue<FlowDirection>(_value));
453
455 else if (_key == "MaxListLength")
456 setMaxListLength(utility::parseValue<int>(_value));
457
459 else if (_key == "SmoothShow")
460 setSmoothShow(utility::parseValue<bool>(_value));
461
462 // не коментировать
463 else if (_key == "AddItem")
465
466 else
467 {
469 return;
470 }
471
473 }
474
476 {
477 return mList->getItemCount();
478 }
479
481 {
483 }
484
486 {
487 return mItemIndex;
488 }
489
491 {
493 }
494
496 {
498 }
499
501 {
502 return mList->getItemNameAt(_index);
503 }
504
506 {
507 mList->beginToItemAt(_index);
508 }
509
511 {
512 if (getItemCount())
513 beginToItemAt(0);
514 }
515
517 {
518 if (getItemCount())
520 }
521
523 {
526 }
527
529 {
530 return mModeDrop;
531 }
532
534 {
535 mShowSmooth = _value;
536 }
537
539 {
540 return mShowSmooth;
541 }
542
544 {
545 mMaxListLength = _value;
546 }
547
549 {
550 return mMaxListLength;
551 }
552
554 {
555 return mFlowDirection;
556 }
557
558 void ComboBox::notifyToolTip(Widget* _sender, const ToolTipInfo& _info)
559 {
560 if (getNeedToolTip())
561 eventToolTip(this, _info);
562 }
563
565 {
566 return getItemCount();
567 }
568
570 {
571 addItem(_name);
572 }
573
575 {
577 }
578
580 {
582 }
583
585 {
586 return getItemNameAt(_index);
587 }
588
590 {
592 if (mList != nullptr)
593 mList->_resetContainer(_update);
594 }
595
596} // 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()
static ControllerManager & getInstance()
void setEditStatic(bool _value)
EventPair< EventHandle_WidgetVoid, EventHandle_EditPtr > eventEditTextChange
void setCaption(const UString &_value) override
EventObsolete m_eventObsolete
Type * castType(bool _throw=true)
static InputManager & getInstance()
static LanguageManager & getInstance()
widget description should be here.
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)
static const std::string & getClassTypeName()
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.
EventHandle_WidgetStringString eventChangeProperty
void assignWidget(T *&_widget, const std::string &_name)
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
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
const float ALPHA_MAX
const float COMBO_ALPHA_COEF
const size_t ITEM_NONE
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
unsigned int Char
Definition MyGUI_Types.h:50