MyGUI
3.2.1
|
00001 /* 00002 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 00003 * Distributed under the MIT License 00004 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 00005 */ 00006 00007 #include "MyGUI_Precompiled.h" 00008 #include "MyGUI_ComboBox.h" 00009 #include "MyGUI_ControllerManager.h" 00010 #include "MyGUI_InputManager.h" 00011 #include "MyGUI_WidgetManager.h" 00012 #include "MyGUI_Gui.h" 00013 #include "MyGUI_ListBox.h" 00014 #include "MyGUI_Button.h" 00015 #include "MyGUI_ResourceSkin.h" 00016 #include "MyGUI_LayerManager.h" 00017 00018 namespace MyGUI 00019 { 00020 00021 const float COMBO_ALPHA_MAX = ALPHA_MAX; 00022 const float COMBO_ALPHA_MIN = ALPHA_MIN; 00023 const float COMBO_ALPHA_COEF = 4.0f; 00024 00025 ComboBox::ComboBox() : 00026 mButton(nullptr), 00027 mList(nullptr), 00028 mListShow(false), 00029 mMaxListLength(-1), 00030 mItemIndex(ITEM_NONE), 00031 mModeDrop(false), 00032 mDropMouse(false), 00033 mShowSmooth(false), 00034 mFlowDirection(FlowDirection::TopToBottom) 00035 { 00036 } 00037 00038 void ComboBox::initialiseOverride() 00039 { 00040 Base::initialiseOverride(); 00041 00043 assignWidget(mButton, "Button"); 00044 if (mButton != nullptr) 00045 { 00046 mButton->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyButtonPressed); 00047 } 00048 00050 assignWidget(mList, "List"); 00051 00052 if (mList == nullptr) 00053 { 00054 std::string list_skin = getUserString("ListSkin"); 00055 std::string list_layer = getUserString("ListLayer"); 00056 00057 mList = static_cast<ListBox*>(_createSkinWidget(WidgetStyle::Popup, ListBox::getClassTypeName(), list_skin, IntCoord(), Align::Default, list_layer)); 00058 } 00059 00060 if (mList != nullptr) 00061 { 00062 mList->setActivateOnClick(true); 00063 00064 mList->setVisible(false); 00065 mList->eventKeyLostFocus += newDelegate(this, &ComboBox::notifyListLostFocus); 00066 mList->eventListSelectAccept += newDelegate(this, &ComboBox::notifyListSelectAccept); 00067 mList->eventListMouseItemActivate += newDelegate(this, &ComboBox::notifyListMouseItemActivate); 00068 mList->eventListChangePosition += newDelegate(this, &ComboBox::notifyListChangePosition); 00069 00070 mList->setNeedToolTip(true); 00071 mList->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip); 00072 } 00073 00074 // подписываем дочерние классы на скролл 00075 if (mClient != nullptr) 00076 { 00077 mClient->eventMouseWheel += newDelegate(this, &ComboBox::notifyMouseWheel); 00078 mClient->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyMousePressed); 00079 00080 mClient->setNeedToolTip(true); 00081 mClient->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip); 00082 } 00083 00084 // подписываемся на изменения текста 00085 eventEditTextChange += newDelegate(this, &ComboBox::notifyEditTextChange); 00086 } 00087 00088 void ComboBox::shutdownOverride() 00089 { 00090 mList = nullptr; 00091 mButton = nullptr; 00092 mClient = nullptr; 00093 00094 Base::shutdownOverride(); 00095 } 00096 00097 void ComboBox::notifyButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id) 00098 { 00099 if (MouseButton::Left != _id) 00100 return; 00101 00102 mDropMouse = true; 00103 00104 if (mListShow) 00105 hideList(); 00106 else 00107 showList(); 00108 } 00109 00110 void ComboBox::notifyListLostFocus(Widget* _sender, Widget* _new) 00111 { 00112 if (mDropMouse) 00113 { 00114 mDropMouse = false; 00115 Widget* focus = InputManager::getInstance().getMouseFocusWidget(); 00116 00117 // кнопка сама уберет список 00118 if (focus == mButton) 00119 return; 00120 00121 // в режиме дропа все окна учавствуют 00122 if (mModeDrop && focus == mClient) 00123 return; 00124 } 00125 00126 hideList(); 00127 } 00128 00129 void ComboBox::notifyListSelectAccept(ListBox* _widget, size_t _position) 00130 { 00131 mItemIndex = _position; 00132 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : ""); 00133 00134 mDropMouse = false; 00135 InputManager::getInstance().setKeyFocusWidget(this); 00136 00137 if (mModeDrop) 00138 { 00139 _resetContainer(false); 00140 00141 eventComboAccept.m_eventObsolete(this); 00142 eventComboAccept.m_event(this, mItemIndex); 00143 } 00144 } 00145 00146 void ComboBox::notifyListChangePosition(ListBox* _widget, size_t _position) 00147 { 00148 mItemIndex = _position; 00149 00150 _resetContainer(false); 00151 00152 eventComboChangePosition(this, _position); 00153 } 00154 00155 void ComboBox::onKeyButtonPressed(KeyCode _key, Char _char) 00156 { 00157 Base::onKeyButtonPressed(_key, _char); 00158 00159 // при нажатии вниз, показываем лист 00160 if (_key == KeyCode::ArrowDown) 00161 { 00162 // выкидываем список только если мыша свободна 00163 if (!InputManager::getInstance().isCaptureMouse()) 00164 { 00165 showList(); 00166 } 00167 } 00168 // нажат ввод в окне редиктирования 00169 else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter)) 00170 { 00171 _resetContainer(false); 00172 00173 eventComboAccept.m_eventObsolete(this); 00174 eventComboAccept.m_event(this, mItemIndex); 00175 } 00176 } 00177 00178 void ComboBox::notifyListMouseItemActivate(ListBox* _widget, size_t _position) 00179 { 00180 mItemIndex = _position; 00181 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : ""); 00182 00183 InputManager::getInstance().setKeyFocusWidget(this); 00184 00185 if (mModeDrop) 00186 { 00187 _resetContainer(false); 00188 00189 eventComboAccept.m_eventObsolete(this); 00190 eventComboAccept.m_event(this, mItemIndex); 00191 } 00192 } 00193 00194 void ComboBox::notifyMouseWheel(Widget* _sender, int _rel) 00195 { 00196 if (mList->getItemCount() == 0) 00197 return; 00198 if (InputManager::getInstance().getKeyFocusWidget() != this) 00199 return; 00200 if (InputManager::getInstance().isCaptureMouse()) 00201 return; 00202 00203 if (_rel > 0) 00204 { 00205 if (mItemIndex != 0) 00206 { 00207 if (mItemIndex == ITEM_NONE) 00208 mItemIndex = 0; 00209 else 00210 mItemIndex --; 00211 Base::setCaption(mList->getItemNameAt(mItemIndex)); 00212 mList->setIndexSelected(mItemIndex); 00213 mList->beginToItemAt(mItemIndex); 00214 00215 _resetContainer(false); 00216 00217 eventComboChangePosition(this, mItemIndex); 00218 } 00219 } 00220 else if (_rel < 0) 00221 { 00222 if ((mItemIndex + 1) < mList->getItemCount()) 00223 { 00224 if (mItemIndex == ITEM_NONE) 00225 mItemIndex = 0; 00226 else 00227 mItemIndex ++; 00228 Base::setCaption(mList->getItemNameAt(mItemIndex)); 00229 mList->setIndexSelected(mItemIndex); 00230 mList->beginToItemAt(mItemIndex); 00231 00232 _resetContainer(false); 00233 00234 eventComboChangePosition(this, mItemIndex); 00235 } 00236 } 00237 } 00238 00239 void ComboBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id) 00240 { 00241 // обязательно отдаем отцу, а то мы у него в наглую отняли 00242 Base::notifyMousePressed(_sender, _left, _top, _id); 00243 00244 mDropMouse = true; 00245 00246 // показываем список 00247 if (mModeDrop) 00248 notifyButtonPressed(nullptr, _left, _top, _id); 00249 } 00250 00251 void ComboBox::notifyEditTextChange(EditBox* _sender) 00252 { 00253 // сбрасываем выделенный элемент 00254 if (ITEM_NONE != mItemIndex) 00255 { 00256 mItemIndex = ITEM_NONE; 00257 mList->setIndexSelected(mItemIndex); 00258 mList->beginToItemFirst(); 00259 00260 _resetContainer(false); 00261 00262 eventComboChangePosition(this, mItemIndex); 00263 } 00264 } 00265 00266 void ComboBox::showList() 00267 { 00268 // пустой список не показываем 00269 if (mList->getItemCount() == 0) 00270 return; 00271 00272 mListShow = true; 00273 00274 IntCoord coord = calculateListPosition(); 00275 mList->setCoord(coord); 00276 00277 if (mShowSmooth) 00278 { 00279 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MAX, COMBO_ALPHA_COEF, true); 00280 ControllerManager::getInstance().addItem(mList, controller); 00281 } 00282 else 00283 { 00284 mList->setVisible(true); 00285 } 00286 00287 InputManager::getInstance().setKeyFocusWidget(mList); 00288 } 00289 00290 void ComboBox::actionWidgetHide(Widget* _widget, ControllerItem* _controller) 00291 { 00292 _widget->setVisible(false); 00293 _widget->setEnabled(true); 00294 } 00295 00296 void ComboBox::hideList() 00297 { 00298 mListShow = false; 00299 00300 if (mShowSmooth) 00301 { 00302 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MIN, COMBO_ALPHA_COEF, false); 00303 controller->eventPostAction += newDelegate(this, &ComboBox::actionWidgetHide); 00304 ControllerManager::getInstance().addItem(mList, controller); 00305 } 00306 else 00307 { 00308 mList->setVisible(false); 00309 } 00310 } 00311 00312 void ComboBox::setIndexSelected(size_t _index) 00313 { 00314 MYGUI_ASSERT_RANGE_AND_NONE(_index, mList->getItemCount(), "ComboBox::setIndexSelected"); 00315 mItemIndex = _index; 00316 mList->setIndexSelected(_index); 00317 if (_index == ITEM_NONE) 00318 { 00319 Base::setCaption(""); 00320 return; 00321 } 00322 Base::setCaption(mList->getItemNameAt(_index)); 00323 Base::updateView(); // hook for update 00324 } 00325 00326 void ComboBox::setItemNameAt(size_t _index, const UString& _name) 00327 { 00328 mList->setItemNameAt(_index, _name); 00329 mItemIndex = ITEM_NONE;//FIXME 00330 mList->setIndexSelected(mItemIndex);//FIXME 00331 } 00332 00333 void ComboBox::setItemDataAt(size_t _index, Any _data) 00334 { 00335 mList->setItemDataAt(_index, _data); 00336 mItemIndex = ITEM_NONE;//FIXME 00337 mList->setIndexSelected(mItemIndex);//FIXME 00338 } 00339 00340 void ComboBox::insertItemAt(size_t _index, const UString& _item, Any _data) 00341 { 00342 mList->insertItemAt(_index, _item, _data); 00343 mItemIndex = ITEM_NONE;//FIXME 00344 mList->setIndexSelected(mItemIndex);//FIXME 00345 } 00346 00347 void ComboBox::removeItemAt(size_t _index) 00348 { 00349 mList->removeItemAt(_index); 00350 mItemIndex = ITEM_NONE;//FIXME 00351 mList->clearIndexSelected();//FIXME 00352 } 00353 00354 void ComboBox::removeAllItems() 00355 { 00356 mItemIndex = ITEM_NONE;//FIXME 00357 mList->removeAllItems();//FIXME заново созданные строки криво стоят 00358 } 00359 00360 void ComboBox::setComboModeDrop(bool _drop) 00361 { 00362 mModeDrop = _drop; 00363 setEditStatic(mModeDrop); 00364 } 00365 00366 ControllerFadeAlpha* ComboBox::createControllerFadeAlpha(float _alpha, float _coef, bool _enable) 00367 { 00368 ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName()); 00369 ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>(); 00370 00371 controller->setAlpha(_alpha); 00372 controller->setCoef(_coef); 00373 controller->setEnabled(_enable); 00374 00375 return controller; 00376 } 00377 00378 size_t ComboBox::findItemIndexWith(const UString& _name) 00379 { 00380 return mList->findItemIndexWith(_name); 00381 } 00382 00383 void ComboBox::setFlowDirection(FlowDirection _value) 00384 { 00385 mFlowDirection = _value; 00386 } 00387 00388 IntCoord ComboBox::calculateListPosition() 00389 { 00390 int length = 0; 00391 if (mFlowDirection.isVertical()) 00392 length = mList->getOptimalHeight(); 00393 else 00394 length = mMaxListLength; 00395 00396 if (mMaxListLength > 0 && length > mMaxListLength) 00397 length = mMaxListLength; 00398 00399 // берем глобальные координаты выджета 00400 IntCoord coord = getAbsoluteCoord(); 00401 // размер леера 00402 IntSize sizeView = mList->getParentSize(); 00403 00404 if (mFlowDirection == FlowDirection::TopToBottom) 00405 { 00406 if ((coord.bottom() + length) <= sizeView.height) 00407 coord.top += coord.height; 00408 else 00409 coord.top -= length; 00410 coord.height = length; 00411 } 00412 else if (mFlowDirection == FlowDirection::BottomToTop) 00413 { 00414 if ((coord.top - length) >= 0) 00415 coord.top -= length; 00416 else 00417 coord.top += coord.height; 00418 coord.height = length; 00419 } 00420 else if (mFlowDirection == FlowDirection::LeftToRight) 00421 { 00422 if ((coord.right() + length) <= sizeView.width) 00423 coord.left += coord.width; 00424 else 00425 coord.left -= length; 00426 coord.width = length; 00427 } 00428 else if (mFlowDirection == FlowDirection::RightToLeft) 00429 { 00430 if ((coord.left - length) >= 0) 00431 coord.left -= length; 00432 else 00433 coord.left += coord.width; 00434 coord.width = length; 00435 } 00436 00437 return coord; 00438 } 00439 00440 void ComboBox::setPropertyOverride(const std::string& _key, const std::string& _value) 00441 { 00443 if (_key == "ModeDrop") 00444 setComboModeDrop(utility::parseValue<bool>(_value)); 00445 00447 else if (_key == "FlowDirection") 00448 setFlowDirection(utility::parseValue<FlowDirection>(_value)); 00449 00451 else if (_key == "MaxListLength") 00452 setMaxListLength(utility::parseValue<int>(_value)); 00453 00455 else if (_key == "SmoothShow") 00456 setSmoothShow(utility::parseValue<bool>(_value)); 00457 00458 // не коментировать 00459 else if (_key == "AddItem") 00460 addItem(_value); 00461 00462 else 00463 { 00464 Base::setPropertyOverride(_key, _value); 00465 return; 00466 } 00467 00468 eventChangeProperty(this, _key, _value); 00469 } 00470 00471 size_t ComboBox::getItemCount() const 00472 { 00473 return mList->getItemCount(); 00474 } 00475 00476 void ComboBox::addItem(const UString& _name, Any _data) 00477 { 00478 return insertItemAt(ITEM_NONE, _name, _data); 00479 } 00480 00481 size_t ComboBox::getIndexSelected() const 00482 { 00483 return mItemIndex; 00484 } 00485 00486 void ComboBox::clearIndexSelected() 00487 { 00488 setIndexSelected(ITEM_NONE); 00489 } 00490 00491 void ComboBox::clearItemDataAt(size_t _index) 00492 { 00493 setItemDataAt(_index, Any::Null); 00494 } 00495 00496 const UString& ComboBox::getItemNameAt(size_t _index) 00497 { 00498 return mList->getItemNameAt(_index); 00499 } 00500 00501 void ComboBox::beginToItemAt(size_t _index) 00502 { 00503 mList->beginToItemAt(_index); 00504 } 00505 00506 void ComboBox::beginToItemFirst() 00507 { 00508 if (getItemCount()) 00509 beginToItemAt(0); 00510 } 00511 00512 void ComboBox::beginToItemLast() 00513 { 00514 if (getItemCount()) 00515 beginToItemAt(getItemCount() - 1); 00516 } 00517 00518 void ComboBox::beginToItemSelected() 00519 { 00520 if (getIndexSelected() != ITEM_NONE) 00521 beginToItemAt(getIndexSelected()); 00522 } 00523 00524 bool ComboBox::getComboModeDrop() const 00525 { 00526 return mModeDrop; 00527 } 00528 00529 void ComboBox::setSmoothShow(bool _value) 00530 { 00531 mShowSmooth = _value; 00532 } 00533 00534 bool ComboBox::getSmoothShow() const 00535 { 00536 return mShowSmooth; 00537 } 00538 00539 void ComboBox::setMaxListLength(int _value) 00540 { 00541 mMaxListLength = _value; 00542 } 00543 00544 int ComboBox::getMaxListLength() const 00545 { 00546 return mMaxListLength; 00547 } 00548 00549 FlowDirection ComboBox::getFlowDirection() const 00550 { 00551 return mFlowDirection; 00552 } 00553 00554 void ComboBox::notifyToolTip(Widget* _sender, const ToolTipInfo& _info) 00555 { 00556 if (getNeedToolTip()) 00557 eventToolTip(this, _info); 00558 } 00559 00560 size_t ComboBox::_getItemCount() 00561 { 00562 return getItemCount(); 00563 } 00564 00565 void ComboBox::_addItem(const MyGUI::UString& _name) 00566 { 00567 addItem(_name); 00568 } 00569 00570 void ComboBox::_removeItemAt(size_t _index) 00571 { 00572 removeItemAt(_index); 00573 } 00574 00575 void ComboBox::_setItemNameAt(size_t _index, const UString& _name) 00576 { 00577 setItemNameAt(_index, _name); 00578 } 00579 00580 const UString& ComboBox::_getItemNameAt(size_t _index) 00581 { 00582 return getItemNameAt(_index); 00583 } 00584 00585 void ComboBox::_resetContainer(bool _update) 00586 { 00587 Base::_resetContainer(_update); 00588 if (mList != nullptr) 00589 mList->_resetContainer(_update); 00590 } 00591 00592 } // namespace MyGUI