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