MyGUI
3.2.0
|
00001 00006 /* 00007 This file is part of MyGUI. 00008 00009 MyGUI is free software: you can redistribute it and/or modify 00010 it under the terms of the GNU Lesser General Public License as published by 00011 the Free Software Foundation, either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 MyGUI is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 along with MyGUI. If not, see <http://www.gnu.org/licenses/>. 00021 */ 00022 #include "MyGUI_Precompiled.h" 00023 #include "MyGUI_ComboBox.h" 00024 #include "MyGUI_ControllerManager.h" 00025 #include "MyGUI_InputManager.h" 00026 #include "MyGUI_WidgetManager.h" 00027 #include "MyGUI_Gui.h" 00028 #include "MyGUI_ListBox.h" 00029 #include "MyGUI_Button.h" 00030 #include "MyGUI_ResourceSkin.h" 00031 #include "MyGUI_LayerManager.h" 00032 00033 namespace MyGUI 00034 { 00035 00036 const float COMBO_ALPHA_MAX = ALPHA_MAX; 00037 const float COMBO_ALPHA_MIN = ALPHA_MIN; 00038 const float COMBO_ALPHA_COEF = 4.0f; 00039 00040 ComboBox::ComboBox() : 00041 mButton(nullptr), 00042 mList(nullptr), 00043 mListShow(false), 00044 mMaxListLength(-1), 00045 mItemIndex(ITEM_NONE), 00046 mModeDrop(false), 00047 mDropMouse(false), 00048 mShowSmooth(false), 00049 mFlowDirection(FlowDirection::TopToBottom) 00050 { 00051 } 00052 00053 void ComboBox::initialiseOverride() 00054 { 00055 Base::initialiseOverride(); 00056 00057 assignWidget(mButton, "Button"); 00058 if (mButton != nullptr) 00059 { 00060 mButton->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyButtonPressed); 00061 } 00062 00063 assignWidget(mList, "List"); 00064 00065 if (mList == nullptr) 00066 { 00067 std::string list_skin = getUserString("ListSkin"); 00068 std::string list_layer = getUserString("ListLayer"); 00069 00070 mList = static_cast<ListBox*>(_createSkinWidget(WidgetStyle::Popup, ListBox::getClassTypeName(), list_skin, IntCoord(), Align::Default, list_layer)); 00071 } 00072 00073 if (mList != nullptr) 00074 { 00075 mList->setVisible(false); 00076 mList->eventKeyLostFocus += newDelegate(this, &ComboBox::notifyListLostFocus); 00077 mList->eventListSelectAccept += newDelegate(this, &ComboBox::notifyListSelectAccept); 00078 mList->eventListMouseItemActivate += newDelegate(this, &ComboBox::notifyListMouseItemActivate); 00079 mList->eventListChangePosition += newDelegate(this, &ComboBox::notifyListChangePosition); 00080 00081 mList->setNeedToolTip(true); 00082 mList->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip); 00083 } 00084 00085 // подписываем дочерние классы на скролл 00086 if (mClient != nullptr) 00087 { 00088 mClient->eventMouseWheel += newDelegate(this, &ComboBox::notifyMouseWheel); 00089 mClient->eventMouseButtonPressed += newDelegate(this, &ComboBox::notifyMousePressed); 00090 00091 mClient->setNeedToolTip(true); 00092 mClient->eventToolTip += newDelegate(this, &ComboBox::notifyToolTip); 00093 } 00094 00095 // подписываемся на изменения текста 00096 eventEditTextChange += newDelegate(this, &ComboBox::notifyEditTextChange); 00097 } 00098 00099 void ComboBox::shutdownOverride() 00100 { 00101 mList = nullptr; 00102 mButton = nullptr; 00103 mClient = nullptr; 00104 00105 Base::shutdownOverride(); 00106 } 00107 00108 void ComboBox::notifyButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id) 00109 { 00110 if (MouseButton::Left != _id) 00111 return; 00112 00113 mDropMouse = true; 00114 00115 if (mListShow) 00116 hideList(); 00117 else 00118 showList(); 00119 } 00120 00121 void ComboBox::notifyListLostFocus(Widget* _sender, Widget* _new) 00122 { 00123 if (mDropMouse) 00124 { 00125 mDropMouse = false; 00126 Widget* focus = InputManager::getInstance().getMouseFocusWidget(); 00127 00128 // кнопка сама уберет список 00129 if (focus == mButton) 00130 return; 00131 00132 // в режиме дропа все окна учавствуют 00133 if (mModeDrop && focus == mClient) 00134 return; 00135 } 00136 00137 hideList(); 00138 } 00139 00140 void ComboBox::notifyListSelectAccept(ListBox* _widget, size_t _position) 00141 { 00142 mItemIndex = _position; 00143 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : ""); 00144 00145 mDropMouse = false; 00146 InputManager::getInstance().setKeyFocusWidget(this); 00147 00148 if (mModeDrop) 00149 { 00150 _resetContainer(false); 00151 00152 eventComboAccept.m_eventObsolete(this); 00153 eventComboAccept.m_event(this, mItemIndex); 00154 } 00155 } 00156 00157 void ComboBox::notifyListChangePosition(ListBox* _widget, size_t _position) 00158 { 00159 mItemIndex = _position; 00160 00161 _resetContainer(false); 00162 00163 eventComboChangePosition(this, _position); 00164 } 00165 00166 void ComboBox::onKeyButtonPressed(KeyCode _key, Char _char) 00167 { 00168 Base::onKeyButtonPressed(_key, _char); 00169 00170 // при нажатии вниз, показываем лист 00171 if (_key == KeyCode::ArrowDown) 00172 { 00173 // выкидываем список только если мыша свободна 00174 if (!InputManager::getInstance().isCaptureMouse()) 00175 { 00176 showList(); 00177 } 00178 } 00179 // нажат ввод в окне редиктирования 00180 else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter)) 00181 { 00182 _resetContainer(false); 00183 00184 eventComboAccept.m_eventObsolete(this); 00185 eventComboAccept.m_event(this, mItemIndex); 00186 } 00187 } 00188 00189 void ComboBox::notifyListMouseItemActivate(ListBox* _widget, size_t _position) 00190 { 00191 mItemIndex = _position; 00192 Base::setCaption(mItemIndex != ITEM_NONE ? mList->getItemNameAt(mItemIndex) : ""); 00193 00194 InputManager::getInstance().setKeyFocusWidget(this); 00195 00196 if (mModeDrop) 00197 { 00198 _resetContainer(false); 00199 00200 eventComboAccept.m_eventObsolete(this); 00201 eventComboAccept.m_event(this, mItemIndex); 00202 } 00203 } 00204 00205 void ComboBox::notifyMouseWheel(Widget* _sender, int _rel) 00206 { 00207 if (mList->getItemCount() == 0) 00208 return; 00209 if (InputManager::getInstance().getKeyFocusWidget() != this) 00210 return; 00211 if (InputManager::getInstance().isCaptureMouse()) 00212 return; 00213 00214 if (_rel > 0) 00215 { 00216 if (mItemIndex != 0) 00217 { 00218 if (mItemIndex == ITEM_NONE) 00219 mItemIndex = 0; 00220 else 00221 mItemIndex --; 00222 Base::setCaption(mList->getItemNameAt(mItemIndex)); 00223 mList->setIndexSelected(mItemIndex); 00224 mList->beginToItemAt(mItemIndex); 00225 00226 _resetContainer(false); 00227 00228 eventComboChangePosition(this, mItemIndex); 00229 } 00230 } 00231 else if (_rel < 0) 00232 { 00233 if ((mItemIndex + 1) < mList->getItemCount()) 00234 { 00235 if (mItemIndex == ITEM_NONE) 00236 mItemIndex = 0; 00237 else 00238 mItemIndex ++; 00239 Base::setCaption(mList->getItemNameAt(mItemIndex)); 00240 mList->setIndexSelected(mItemIndex); 00241 mList->beginToItemAt(mItemIndex); 00242 00243 _resetContainer(false); 00244 00245 eventComboChangePosition(this, mItemIndex); 00246 } 00247 } 00248 } 00249 00250 void ComboBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id) 00251 { 00252 // обязательно отдаем отцу, а то мы у него в наглую отняли 00253 Base::notifyMousePressed(_sender, _left, _top, _id); 00254 00255 mDropMouse = true; 00256 00257 // показываем список 00258 if (mModeDrop) 00259 notifyButtonPressed(nullptr, _left, _top, _id); 00260 } 00261 00262 void ComboBox::notifyEditTextChange(EditBox* _sender) 00263 { 00264 // сбрасываем выделенный элемент 00265 if (ITEM_NONE != mItemIndex) 00266 { 00267 mItemIndex = ITEM_NONE; 00268 mList->setIndexSelected(mItemIndex); 00269 mList->beginToItemFirst(); 00270 00271 _resetContainer(false); 00272 00273 eventComboChangePosition(this, mItemIndex); 00274 } 00275 } 00276 00277 void ComboBox::showList() 00278 { 00279 // пустой список не показываем 00280 if (mList->getItemCount() == 0) 00281 return; 00282 00283 mListShow = true; 00284 00285 IntCoord coord = calculateListPosition(); 00286 mList->setCoord(coord); 00287 00288 if (mShowSmooth) 00289 { 00290 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MAX, COMBO_ALPHA_COEF, true); 00291 ControllerManager::getInstance().addItem(mList, controller); 00292 } 00293 else 00294 { 00295 mList->setVisible(true); 00296 } 00297 00298 InputManager::getInstance().setKeyFocusWidget(mList); 00299 } 00300 00301 void ComboBox::actionWidgetHide(Widget* _widget) 00302 { 00303 _widget->setVisible(false); 00304 _widget->setEnabled(true); 00305 } 00306 00307 void ComboBox::hideList() 00308 { 00309 mListShow = false; 00310 00311 if (mShowSmooth) 00312 { 00313 ControllerFadeAlpha* controller = createControllerFadeAlpha(COMBO_ALPHA_MIN, COMBO_ALPHA_COEF, false); 00314 controller->eventPostAction += newDelegate(this, &ComboBox::actionWidgetHide); 00315 ControllerManager::getInstance().addItem(mList, controller); 00316 } 00317 else 00318 { 00319 mList->setVisible(false); 00320 } 00321 } 00322 00323 void ComboBox::setIndexSelected(size_t _index) 00324 { 00325 MYGUI_ASSERT_RANGE_AND_NONE(_index, mList->getItemCount(), "ComboBox::setIndexSelected"); 00326 mItemIndex = _index; 00327 mList->setIndexSelected(_index); 00328 if (_index == ITEM_NONE) 00329 { 00330 Base::setCaption(""); 00331 return; 00332 } 00333 Base::setCaption(mList->getItemNameAt(_index)); 00334 Base::updateView(); // hook for update 00335 } 00336 00337 void ComboBox::setItemNameAt(size_t _index, const UString& _name) 00338 { 00339 mList->setItemNameAt(_index, _name); 00340 mItemIndex = ITEM_NONE;//FIXME 00341 mList->setIndexSelected(mItemIndex);//FIXME 00342 } 00343 00344 void ComboBox::setItemDataAt(size_t _index, Any _data) 00345 { 00346 mList->setItemDataAt(_index, _data); 00347 mItemIndex = ITEM_NONE;//FIXME 00348 mList->setIndexSelected(mItemIndex);//FIXME 00349 } 00350 00351 void ComboBox::insertItemAt(size_t _index, const UString& _item, Any _data) 00352 { 00353 mList->insertItemAt(_index, _item, _data); 00354 mItemIndex = ITEM_NONE;//FIXME 00355 mList->setIndexSelected(mItemIndex);//FIXME 00356 } 00357 00358 void ComboBox::removeItemAt(size_t _index) 00359 { 00360 mList->removeItemAt(_index); 00361 mItemIndex = ITEM_NONE;//FIXME 00362 mList->clearIndexSelected();//FIXME 00363 } 00364 00365 void ComboBox::removeAllItems() 00366 { 00367 mItemIndex = ITEM_NONE;//FIXME 00368 mList->removeAllItems();//FIXME заново созданные строки криво стоят 00369 } 00370 00371 void ComboBox::setComboModeDrop(bool _drop) 00372 { 00373 mModeDrop = _drop; 00374 setEditStatic(mModeDrop); 00375 } 00376 00377 ControllerFadeAlpha* ComboBox::createControllerFadeAlpha(float _alpha, float _coef, bool _enable) 00378 { 00379 ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName()); 00380 ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>(); 00381 00382 controller->setAlpha(_alpha); 00383 controller->setCoef(_coef); 00384 controller->setEnabled(_enable); 00385 00386 return controller; 00387 } 00388 00389 size_t ComboBox::findItemIndexWith(const UString& _name) 00390 { 00391 return mList->findItemIndexWith(_name); 00392 } 00393 00394 void ComboBox::setFlowDirection(FlowDirection _value) 00395 { 00396 mFlowDirection = _value; 00397 } 00398 00399 IntCoord ComboBox::calculateListPosition() 00400 { 00401 int length = 0; 00402 if (mFlowDirection.isVertical()) 00403 length = mList->getOptimalHeight(); 00404 else 00405 length = mMaxListLength; 00406 00407 if (mMaxListLength > 0 && length > mMaxListLength) 00408 length = mMaxListLength; 00409 00410 // берем глобальные координаты выджета 00411 IntCoord coord = getAbsoluteCoord(); 00412 // размер леера 00413 IntSize sizeView = mList->getParentSize(); 00414 00415 if (mFlowDirection == FlowDirection::TopToBottom) 00416 { 00417 if ((coord.bottom() + length) <= sizeView.height) 00418 coord.top += coord.height; 00419 else 00420 coord.top -= length; 00421 coord.height = length; 00422 } 00423 else if (mFlowDirection == FlowDirection::BottomToTop) 00424 { 00425 if ((coord.top - length) >= 0) 00426 coord.top -= length; 00427 else 00428 coord.top += coord.height; 00429 coord.height = length; 00430 } 00431 else if (mFlowDirection == FlowDirection::LeftToRight) 00432 { 00433 if ((coord.right() + length) <= sizeView.width) 00434 coord.left += coord.width; 00435 else 00436 coord.left -= length; 00437 coord.width = length; 00438 } 00439 else if (mFlowDirection == FlowDirection::RightToLeft) 00440 { 00441 if ((coord.left - length) >= 0) 00442 coord.left -= length; 00443 else 00444 coord.left += coord.width; 00445 coord.width = length; 00446 } 00447 00448 return coord; 00449 } 00450 00451 void ComboBox::setPropertyOverride(const std::string& _key, const std::string& _value) 00452 { 00453 if (_key == "ModeDrop") 00454 setComboModeDrop(utility::parseValue<bool>(_value)); 00455 else if (_key == "FlowDirection") 00456 setFlowDirection(utility::parseValue<FlowDirection>(_value)); 00457 else if (_key == "MaxListLength") 00458 setMaxListLength(utility::parseValue<int>(_value)); 00459 else if (_key == "SmoothShow") 00460 setSmoothShow(utility::parseValue<bool>(_value)); 00461 else if (_key == "AddItem") 00462 addItem(_value); 00463 else 00464 { 00465 Base::setPropertyOverride(_key, _value); 00466 return; 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