• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

MyGUI_ComboBox.cpp

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

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1