MyGUI  3.2.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"
17 
18 namespace MyGUI
19 {
20 
21  const float COMBO_ALPHA_MAX = ALPHA_MAX;
22  const float COMBO_ALPHA_MIN = ALPHA_MIN;
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 (mClient != nullptr)
76  {
77  mClient->eventMouseWheel += newDelegate(this, &ComboBox::notifyMouseWheel);
78  mClient->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyMousePressed);
79 
80  mClient->setNeedToolTip(true);
81  mClient->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip);
82  }
83 
84  // подписываемся на изменения текста
85  eventEditTextChange += newDelegate(this, &ComboBox::notifyEditTextChange);
86  }
87 
89  {
90  mList = nullptr;
91  mButton = nullptr;
92  mClient = nullptr;
93 
95  }
96 
97  void ComboBox::notifyButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
98  {
99  if (MouseButton::Left != _id)
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;
116 
117  // кнопка сама уберет список
118  if (focus == mButton)
119  return;
120 
121  // в режиме дропа все окна учавствуют
122  if (mModeDrop && focus == mClient)
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;
136 
137  if (mModeDrop)
138  {
139  _resetContainer(false);
140 
141  eventComboAccept.m_eventObsolete(this);
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  {
157  Base::onKeyButtonPressed(_key, _char);
158 
159  // при нажатии вниз, показываем лист
160  if (_key == KeyCode::ArrowDown)
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 
173  eventComboAccept.m_eventObsolete(this);
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 
184 
185  if (mModeDrop)
186  {
187  _resetContainer(false);
188 
189  eventComboAccept.m_eventObsolete(this);
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;
199  return;
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  mListShow = true;
273 
274  IntCoord coord = calculateListPosition();
275  mList->setCoord(coord);
276 
277  if (mShowSmooth)
278  {
279  ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MAX, COMBO_ALPHA_COEF, true);
280  ControllerManager::getInstance().addItem(mList, controller);
281  }
282  else
283  {
284  mList->setVisible(true);
285  }
286 
288  }
289 
290  void ComboBox::actionWidgetHide(Widget* _widget, ControllerItem* _controller)
291  {
292  _widget->setVisible(false);
293  _widget->setEnabled(true);
294  }
295 
296  void ComboBox::hideList()
297  {
298  mListShow = false;
299 
300  if (mShowSmooth)
301  {
302  ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MIN, COMBO_ALPHA_COEF, false);
303  controller->eventPostAction += newDelegate(this, &ComboBox::actionWidgetHide);
304  ControllerManager::getInstance().addItem(mList, controller);
305  }
306  else
307  {
308  mList->setVisible(false);
309  }
310  }
311 
312  void ComboBox::setIndexSelected(size_t _index)
313  {
314  MYGUI_ASSERT_RANGE_AND_NONE(_index, mList->getItemCount(), "ComboBox::setIndexSelected");
315  mItemIndex = _index;
316  mList->setIndexSelected(_index);
317  if (_index == ITEM_NONE)
318  {
319  Base::setCaption("");
320  return;
321  }
322  Base::setCaption(mList->getItemNameAt(_index));
323  Base::updateView(); // hook for update
324  }
325 
326  void ComboBox::setItemNameAt(size_t _index, const UString& _name)
327  {
328  mList->setItemNameAt(_index, _name);
329  mItemIndex = ITEM_NONE;//FIXME
330  mList->setIndexSelected(mItemIndex);//FIXME
331  }
332 
333  void ComboBox::setItemDataAt(size_t _index, Any _data)
334  {
335  mList->setItemDataAt(_index, _data);
336  mItemIndex = ITEM_NONE;//FIXME
337  mList->setIndexSelected(mItemIndex);//FIXME
338  }
339 
340  void ComboBox::insertItemAt(size_t _index, const UString& _item, Any _data)
341  {
342  mList->insertItemAt(_index, _item, _data);
343  mItemIndex = ITEM_NONE;//FIXME
344  mList->setIndexSelected(mItemIndex);//FIXME
345  }
346 
347  void ComboBox::removeItemAt(size_t _index)
348  {
349  mList->removeItemAt(_index);
350  mItemIndex = ITEM_NONE;//FIXME
351  mList->clearIndexSelected();//FIXME
352  }
353 
355  {
356  mItemIndex = ITEM_NONE;//FIXME
357  mList->removeAllItems();//FIXME заново созданные строки криво стоят
358  }
359 
360  void ComboBox::setComboModeDrop(bool _drop)
361  {
362  mModeDrop = _drop;
363  setEditStatic(mModeDrop);
364  }
365 
366  ControllerFadeAlpha* ComboBox::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
367  {
369  ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
370 
371  controller->setAlpha(_alpha);
372  controller->setCoef(_coef);
373  controller->setEnabled(_enable);
374 
375  return controller;
376  }
377 
379  {
380  return mList->findItemIndexWith(_name);
381  }
382 
384  {
385  mFlowDirection = _value;
386  }
387 
388  IntCoord ComboBox::calculateListPosition()
389  {
390  int length = 0;
391  if (mFlowDirection.isVertical())
392  length = mList->getOptimalHeight();
393  else
394  length = mMaxListLength;
395 
396  if (mMaxListLength > 0 && length > mMaxListLength)
397  length = mMaxListLength;
398 
399  // берем глобальные координаты выджета
400  IntCoord coord = getAbsoluteCoord();
401  // размер леера
402  IntSize sizeView = mList->getParentSize();
403 
404  if (mFlowDirection == FlowDirection::TopToBottom)
405  {
406  if ((coord.bottom() + length) <= sizeView.height)
407  coord.top += coord.height;
408  else
409  coord.top -= length;
410  coord.height = length;
411  }
412  else if (mFlowDirection == FlowDirection::BottomToTop)
413  {
414  if ((coord.top - length) >= 0)
415  coord.top -= length;
416  else
417  coord.top += coord.height;
418  coord.height = length;
419  }
420  else if (mFlowDirection == FlowDirection::LeftToRight)
421  {
422  if ((coord.right() + length) <= sizeView.width)
423  coord.left += coord.width;
424  else
425  coord.left -= length;
426  coord.width = length;
427  }
428  else if (mFlowDirection == FlowDirection::RightToLeft)
429  {
430  if ((coord.left - length) >= 0)
431  coord.left -= length;
432  else
433  coord.left += coord.width;
434  coord.width = length;
435  }
436 
437  return coord;
438  }
439 
440  void ComboBox::setPropertyOverride(const std::string& _key, const std::string& _value)
441  {
443  if (_key == "ModeDrop")
444  setComboModeDrop(utility::parseValue<bool>(_value));
445 
447  else if (_key == "FlowDirection")
448  setFlowDirection(utility::parseValue<FlowDirection>(_value));
449 
451  else if (_key == "MaxListLength")
452  setMaxListLength(utility::parseValue<int>(_value));
453 
455  else if (_key == "SmoothShow")
456  setSmoothShow(utility::parseValue<bool>(_value));
457 
458  // не коментировать
459  else if (_key == "AddItem")
460  addItem(_value);
461 
462  else
463  {
464  Base::setPropertyOverride(_key, _value);
465  return;
466  }
467 
468  eventChangeProperty(this, _key, _value);
469  }
470 
471  size_t ComboBox::getItemCount() const
472  {
473  return mList->getItemCount();
474  }
475 
476  void ComboBox::addItem(const UString& _name, Any _data)
477  {
478  return insertItemAt(ITEM_NONE, _name, _data);
479  }
480 
482  {
483  return mItemIndex;
484  }
485 
487  {
489  }
490 
491  void ComboBox::clearItemDataAt(size_t _index)
492  {
493  setItemDataAt(_index, Any::Null);
494  }
495 
496  const UString& ComboBox::getItemNameAt(size_t _index)
497  {
498  return mList->getItemNameAt(_index);
499  }
500 
501  void ComboBox::beginToItemAt(size_t _index)
502  {
503  mList->beginToItemAt(_index);
504  }
505 
507  {
508  if (getItemCount())
509  beginToItemAt(0);
510  }
511 
513  {
514  if (getItemCount())
516  }
517 
519  {
520  if (getIndexSelected() != ITEM_NONE)
522  }
523 
525  {
526  return mModeDrop;
527  }
528 
529  void ComboBox::setSmoothShow(bool _value)
530  {
531  mShowSmooth = _value;
532  }
533 
535  {
536  return mShowSmooth;
537  }
538 
539  void ComboBox::setMaxListLength(int _value)
540  {
541  mMaxListLength = _value;
542  }
543 
545  {
546  return mMaxListLength;
547  }
548 
550  {
551  return mFlowDirection;
552  }
553 
554  void ComboBox::notifyToolTip(Widget* _sender, const ToolTipInfo& _info)
555  {
556  if (getNeedToolTip())
557  eventToolTip(this, _info);
558  }
559 
561  {
562  return getItemCount();
563  }
564 
566  {
567  addItem(_name);
568  }
569 
570  void ComboBox::_removeItemAt(size_t _index)
571  {
572  removeItemAt(_index);
573  }
574 
575  void ComboBox::_setItemNameAt(size_t _index, const UString& _name)
576  {
577  setItemNameAt(_index, _name);
578  }
579 
580  const UString& ComboBox::_getItemNameAt(size_t _index)
581  {
582  return getItemNameAt(_index);
583  }
584 
585  void ComboBox::_resetContainer(bool _update)
586  {
587  Base::_resetContainer(_update);
588  if (mList != nullptr)
589  mList->_resetContainer(_update);
590  }
591 
592 } // namespace MyGUI
IntSize getParentSize() const
void addItem(Widget *_widget, ControllerItem *_item)
EventHandle_WidgetInt eventMouseWheel
const float ALPHA_MIN
Definition: MyGUI_Macros.h:20
Widget properties. Skin childs. Widget widget description should be here.
Definition: MyGUI_Widget.h:29
bool getComboModeDrop() const
Get drop list mode flag.
virtual void setPropertyOverride(const std::string &_key, const std::string &_value)
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
const UString & getItemNameAt(size_t _index)
Get item name from specified position.
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 getIndexSelected() const
Get index of selected item (ITEM_NONE if none selected)
void clearIndexSelected()
delegates::IDelegate0 * newDelegate(void(*_func)())
static InputManager & getInstance()
void beginToItemFirst()
Move all elements so first becomes visible.
virtual const UString & _getItemNameAt(size_t _index)
virtual void onKeyButtonPressed(KeyCode _key, Char _char)
virtual void shutdownOverride()
void assignWidget(T *&_widget, const std::string &_name)
Definition: MyGUI_Widget.h:328
const std::string & getUserString(const std::string &_key) const
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:17
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name at a specified position.
Widget * getMouseFocusWidget() const
virtual void setVisible(bool _value)
size_t getItemCount() const
Get number of items.
void removeItemAt(size_t _index)
Remove item at a specified position.
void setIndexSelected(size_t _index)
Select specified _index.
ListBox properties. Skin childs. ListBox widget description should be here.
Definition: MyGUI_ListBox.h:27
#define nullptr
virtual void _resetContainer(bool _update)
void beginToItemAt(size_t _index)
Move all elements so specified becomes visible.
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListChangePosition
types::TCoord< int > IntCoord
Definition: MyGUI_Types.h:35
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)
Replace an item name at a specified position.
FlowDirection getFlowDirection() const
Get direction, where drop down list appears.
int getMaxListLength() const
Set max list length.
virtual void initialiseOverride()
const float COMBO_ALPHA_COEF
virtual void _resetContainer(bool _update)
EventPair< EventHandle_WidgetVoid, EventHandle_ComboBoxPtrSizeT > eventComboAccept
void setActivateOnClick(bool activateOnClick)
void insertItemAt(size_t _index, const UString &_name, Any _data=Any::Null)
Insert an item into a array at a specified position.
size_t getItemCount() const
Get number of items.
void setComboModeDrop(bool _value)
Set drop list mode (text can not be edited)
virtual void setCoord(const IntCoord &_value)
void setKeyFocusWidget(Widget *_widget)
void beginToItemLast()
Move all elements so last becomes visible.
const float ALPHA_MAX
Definition: MyGUI_Macros.h:19
static const std::string & getClassTypeName()
EventHandle_WidgetStringString eventChangeProperty
Definition: MyGUI_Widget.h:266
void setNeedToolTip(bool _value)
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.
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListMouseItemActivate
const UString & getItemNameAt(size_t _index)
Get item name from specified position.
void clearIndexSelected()
Clear item selection.
void removeItemAt(size_t _index)
Remove item at a specified position.
virtual void _setItemNameAt(size_t _index, const UString &_name)
unsigned int Char
Definition: MyGUI_Types.h:51
virtual void setCaption(const UString &_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="")
Type * castType(bool _throw=true)
Definition: MyGUI_IObject.h:18
size_t findItemIndexWith(const UString &_name)
Search item, returns the position of the first occurrence in array or ITEM_NONE if item not found...
int getOptimalHeight()
Return optimal height to fit all items in ListBox.
virtual size_t _getItemCount()
void clearItemDataAt(size_t _index)
Clear an item data at a specified position.
void beginToItemFirst()
Move all elements so first becomes visible.
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListSelectAccept
void beginToItemSelected()
Move all elements so selected becomes visible.
EventHandle_WidgetWidget eventKeyLostFocus
void setFlowDirection(FlowDirection _value)
Set direction, where drop down list appears (TopToBottom by default).
void removeAllItems()
Remove all items.
virtual void _removeItemAt(size_t _index)
bool getSmoothShow() const
Get smooth show of list flag.
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
EventPair< EventHandle_WidgetVoid, EventHandle_EditPtr > eventEditTextChange
EventPair< EventHandle_WidgetSizeT, EventHandle_ComboBoxPtrSizeT > eventComboChangePosition
static const std::string & getClassTypeName()
Definition: MyGUI_ListBox.h:32
void addItem(const UString &_name, Any _data=Any::Null)
Add an item to the end of a array.
Widget * getKeyFocusWidget() const
void setIndexSelected(size_t _index)
void setEditStatic(bool _value)
const float COMBO_ALPHA_MAX
EventHandle_WidgetIntIntButton eventMouseButtonPressed
void beginToItemAt(size_t _index)
Move all elements so specified becomes visible.
const float COMBO_ALPHA_MIN
virtual void _addItem(const MyGUI::UString &_name)
void removeAllItems()
Remove all items.
static AnyEmpty Null
Definition: MyGUI_Any.h:67
EventHandle_WidgetToolTip eventToolTip
ControllerItem * createItem(const std::string &_type)