MyGUI  3.2.1
MyGUI_ItemBox.cpp
Go to the documentation of this file.
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_ItemBox.h"
00009 #include "MyGUI_Button.h"
00010 #include "MyGUI_ScrollBar.h"
00011 #include "MyGUI_ResourceSkin.h"
00012 #include "MyGUI_InputManager.h"
00013 #include "MyGUI_Gui.h"
00014 #include "MyGUI_WidgetTranslate.h"
00015 #include "MyGUI_WidgetManager.h"
00016 
00017 namespace MyGUI
00018 {
00019 
00020     ItemBox::ItemBox() :
00021         mCountItemInLine(0),
00022         mCountLines(0),
00023         mFirstVisibleIndex(0),
00024         mFirstOffsetIndex(0),
00025         mIndexSelect(ITEM_NONE),
00026         mIndexActive(ITEM_NONE),
00027         mIndexAccept(ITEM_NONE),
00028         mIndexRefuse(ITEM_NONE),
00029         mIsFocus(false),
00030         mItemDrag(nullptr),
00031         mAlignVert(true)
00032     {
00033         mChangeContentByResize = true;
00034     }
00035 
00036     void ItemBox::initialiseOverride()
00037     {
00038         Base::initialiseOverride();
00039 
00040         // FIXME нам нужен фокус клавы
00041         setNeedKeyFocus(true);
00042 
00043         mDragLayer = "DragAndDrop";
00044 
00045         if (isUserString("DragLayer"))
00046             mDragLayer = getUserString("DragLayer");
00047 
00049         assignWidget(mClient, "Client");
00050         if (mClient != nullptr)
00051         {
00052             mClient->eventMouseWheel += newDelegate(this, &ItemBox::notifyMouseWheel);
00053             mClient->eventMouseButtonPressed += newDelegate(this, &ItemBox::notifyMouseButtonPressed);
00054             mClient->eventMouseButtonReleased += newDelegate(this, &ItemBox::notifyMouseButtonReleased);
00055             setWidgetClient(mClient);
00056         }
00057 
00059         assignWidget(mVScroll, "VScroll");
00060         if (mVScroll != nullptr)
00061         {
00062             mVScroll->eventScrollChangePosition += newDelegate(this, &ItemBox::notifyScrollChangePosition);
00063         }
00064 
00066         assignWidget(mHScroll, "HScroll");
00067         if (mHScroll != nullptr)
00068         {
00069             mHScroll->eventScrollChangePosition += newDelegate(this, &ItemBox::notifyScrollChangePosition);
00070         }
00071 
00072         // подписываем клиент для драгэндропа
00073         if (mClient != nullptr)
00074             mClient->_setContainer(this);
00075 
00076         requestItemSize();
00077 
00078         updateScrollSize();
00079         updateScrollPosition();
00080     }
00081 
00082     void ItemBox::shutdownOverride()
00083     {
00084         mVScroll = nullptr;
00085         mHScroll = nullptr;
00086         mClient = nullptr;
00087 
00088         Base::shutdownOverride();
00089     }
00090 
00091     void ItemBox::setPosition(const IntPoint& _point)
00092     {
00093         Base::setPosition(_point);
00094     }
00095 
00096     void ItemBox::setSize(const IntSize& _size)
00097     {
00098         Base::setSize(_size);
00099         updateFromResize();
00100     }
00101 
00102     void ItemBox::setCoord(const IntCoord& _coord)
00103     {
00104         Base::setCoord(_coord);
00105         updateFromResize();
00106     }
00107 
00108     void ItemBox::requestItemSize()
00109     {
00110         IntCoord coord(0, 0, 1, 1);
00111 
00112         // спрашиваем размер иконок
00113         requestCoordItem(this, coord, false);
00114 
00115         mSizeItem = coord.size();
00116         MYGUI_ASSERT((mSizeItem.width > 0 && mSizeItem.height > 0), "(mSizeItem.width > 0 && mSizeItem.height > 0)  at requestCoordWidgetItem");
00117     }
00118 
00119     void ItemBox::updateFromResize()
00120     {
00121         requestItemSize();
00122 
00123         updateScrollSize();
00124         updateScrollPosition();
00125 
00126         _updateAllVisible(true);
00127         _resetContainer(true);
00128     }
00129 
00130     void ItemBox::_updateAllVisible(bool _redraw)
00131     {
00132         int count_visible = 0;
00133         if (mAlignVert)
00134         {
00135             count_visible = (_getClientWidget()->getHeight() / mSizeItem.height) + 2;
00136         }
00137         else
00138         {
00139             count_visible = (_getClientWidget()->getWidth() / mSizeItem.width) + 2;
00140         }
00141 
00142         size_t start = (mFirstVisibleIndex * mCountItemInLine);
00143         size_t count = (count_visible * mCountItemInLine) + start;
00144 
00145         size_t index = 0;
00146         for (size_t pos = start; pos < count; ++pos, ++index)
00147         {
00148             // дальше нет айтемов
00149             if (pos >= mItemsInfo.size()) break;
00150 
00151             Widget* item = getItemWidget(index);
00152             if (mAlignVert)
00153             {
00154                 item->setPosition(((int)index % mCountItemInLine) * mSizeItem.width - mContentPosition.left,
00155                     (((int)index / mCountItemInLine) * mSizeItem.height)  - mFirstOffsetIndex);
00156             }
00157             else
00158             {
00159                 item->setPosition((((int)index / mCountItemInLine) * mSizeItem.width)  - mFirstOffsetIndex,
00160                     ((int)index % mCountItemInLine) * mSizeItem.height - mContentPosition.top);
00161             }
00162 
00163             item->setSize(mSizeItem);
00164             item->setVisible(true);
00165 
00166             if (_redraw)
00167             {
00168                 IBDrawItemInfo data(pos, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
00169                 requestDrawItem(this, item, data);
00170             }
00171 
00172         }
00173 
00174         // все виджеты еще есть, то их надо бы скрыть
00175         while (index < mVectorItems.size())
00176         {
00177             mVectorItems[index]->setVisible(false);
00178             index ++;
00179         }
00180     }
00181 
00182     Widget* ItemBox::getItemWidget(size_t _index)
00183     {
00184         // еще нет такого виджета, нуно создать
00185         if (_index == mVectorItems.size())
00186         {
00187             requestItemSize();
00188 
00189             Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(0, 0, mSizeItem.width, mSizeItem.height), Align::Default);
00190 
00191             // вызываем запрос на создание виджета
00192             requestCreateWidgetItem(this, item);
00193 
00194             item->eventMouseWheel += newDelegate(this, &ItemBox::notifyMouseWheel);
00195             item->eventRootMouseChangeFocus += newDelegate(this, &ItemBox::notifyRootMouseChangeFocus);
00196             item->eventMouseButtonPressed += newDelegate(this, &ItemBox::notifyMouseButtonPressed);
00197             item->eventMouseButtonReleased += newDelegate(this, &ItemBox::notifyMouseButtonReleased);
00198             item->eventMouseButtonDoubleClick += newDelegate(this, &ItemBox::notifyMouseButtonDoubleClick);
00199             item->eventMouseDrag += newDelegate(this, &ItemBox::notifyMouseDrag);
00200             item->_setContainer(this);
00201             item->eventKeyButtonPressed += newDelegate(this, &ItemBox::notifyKeyButtonPressed);
00202             item->eventKeyButtonReleased += newDelegate(this, &ItemBox::notifyKeyButtonReleased);
00203 
00204             item->_setInternalData((size_t)mVectorItems.size());
00205 
00206             mVectorItems.push_back(item);
00207         }
00208 
00209         // запрашивать только последовательно
00210         MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ItemBox::getItemWidget");
00211 
00212         return mVectorItems[_index];
00213     }
00214 
00215     void ItemBox::onMouseWheel(int _rel)
00216     {
00217         notifyMouseWheel(nullptr, _rel);
00218 
00219         Base::onMouseWheel(_rel);
00220     }
00221 
00222     void ItemBox::onKeySetFocus(Widget* _old)
00223     {
00224         mIsFocus = true;
00225 
00226         Base::onKeySetFocus(_old);
00227     }
00228 
00229     void ItemBox::onKeyLostFocus(Widget* _new)
00230     {
00231         mIsFocus = false;
00232 
00233         Base::onKeyLostFocus(_new);
00234     }
00235 
00236     void ItemBox::resetCurrentActiveItem()
00237     {
00238         // сбрасываем старую подсветку
00239         if (mIndexActive != ITEM_NONE)
00240         {
00241             size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
00242             size_t index = mIndexActive;
00243             mIndexActive = ITEM_NONE;
00244 
00245             // если видим, то обновляем
00246             if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size())))
00247             {
00248                 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00249 
00250                 requestDrawItem(this, mVectorItems[mIndexActive - start], data);
00251             }
00252         }
00253     }
00254 
00255     void ItemBox::findCurrentActiveItem()
00256     {
00257         MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()");
00258 
00259         const IntPoint& point = InputManager::getInstance().getMousePositionByLayer();
00260 
00261         // сначала проверяем клиентскую зону
00262         const IntRect& rect = _getClientAbsoluteRect();
00263         if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom))
00264         {
00265             return;
00266         }
00267 
00268         for (size_t pos = 0; pos < mVectorItems.size(); ++pos)
00269         {
00270             Widget* item = mVectorItems[pos];
00271             const IntRect& abs_rect = item->getAbsoluteRect();
00272             if ((point.left >= abs_rect.left) && (point.left <= abs_rect.right) && (point.top >= abs_rect.top) && (point.top <= abs_rect.bottom))
00273             {
00274 
00275                 size_t index = calcIndexByWidget(item);
00276                 // при переборе индекс может быть больше, так как может создасться сколько угодно
00277                 if (index < mItemsInfo.size())
00278                 {
00279 
00280                     mIndexActive = index;
00281                     IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00282 
00283                     requestDrawItem(this, item, data);
00284                 }
00285 
00286                 break;
00287             }
00288         }
00289     }
00290 
00291     size_t ItemBox::_getItemIndex(Widget* _item)
00292     {
00293         if (_item == _getClientWidget())
00294             return ITEM_NONE;
00295         size_t index = calcIndexByWidget(_item);
00296         if (index < mItemsInfo.size())
00297             return index;
00298         return ITEM_NONE;
00299     }
00300 
00301     void ItemBox::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
00302     {
00303         if (_index == ITEM_NONE) return;
00304         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::_setContainerItemInfo");
00305 
00306         mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE;
00307         mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE;
00308 
00309         size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
00310         if ((_index >= start) && (_index < (start + mVectorItems.size())))
00311         {
00312             IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00313             requestDrawItem(this, mVectorItems[_index - start], data);
00314         }
00315     }
00316 
00317     void ItemBox::setItemDataAt(size_t _index, Any _data)
00318     {
00319         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::setItemData");
00320         mItemsInfo[_index].data = _data;
00321 
00322         size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
00323         if ((_index >= start) && (_index < (start + mVectorItems.size())))
00324         {
00325             IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
00326             requestDrawItem(this, mVectorItems[_index - start], data);
00327         }
00328 
00329         _resetContainer(true);
00330     }
00331 
00332     void ItemBox::insertItemAt(size_t _index, Any _data)
00333     {
00334         MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ItemBox::insertItemAt");
00335         if (_index == ITEM_NONE) _index = mItemsInfo.size();
00336 
00337         _resetContainer(false);
00338 
00339         resetCurrentActiveItem();
00340 
00341         mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data));
00342 
00343         // расчитываем новый индекс выделения
00344         if (mIndexSelect != ITEM_NONE)
00345         {
00346             if (mIndexSelect >= _index)
00347             {
00348                 mIndexSelect ++;
00349             }
00350         }
00351 
00352         updateScrollSize();
00353         updateScrollPosition();
00354 
00355         findCurrentActiveItem();
00356 
00357         _updateAllVisible(true);
00358     }
00359 
00360     void ItemBox::removeItemAt(size_t _index)
00361     {
00362         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::removeItemAt");
00363 
00364         _resetContainer(false);
00365         resetCurrentActiveItem();
00366 
00367         mItemsInfo.erase(mItemsInfo.begin() + _index);
00368 
00369         // расчитываем новый индекс выделения
00370         if (mIndexSelect != ITEM_NONE)
00371         {
00372             if (mItemsInfo.empty())
00373             {
00374                 mIndexSelect = ITEM_NONE;
00375             }
00376             else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size()))
00377             {
00378                 mIndexSelect --;
00379             }
00380         }
00381 
00382         updateScrollSize();
00383         updateScrollPosition();
00384 
00385         findCurrentActiveItem();
00386 
00387         _updateAllVisible(true);
00388     }
00389 
00390     void ItemBox::removeAllItems()
00391     {
00392         if (mItemsInfo.empty())
00393             return;
00394         _resetContainer(false);
00395 
00396         mItemsInfo.clear();
00397 
00398         mIndexSelect = ITEM_NONE;
00399         mIndexActive = ITEM_NONE;
00400 
00401         updateScrollSize();
00402         updateScrollPosition();
00403 
00404         _updateAllVisible(true);
00405     }
00406 
00407     void ItemBox::redrawItemAt(size_t _index)
00408     {
00409         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::redrawItemAt");
00410 
00411         size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
00412         if ((_index >= start) && (_index < (start + mVectorItems.size())))
00413         {
00414             IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
00415             requestDrawItem(this, mVectorItems[_index - start], data);
00416         }
00417     }
00418 
00419     void ItemBox::setIndexSelected(size_t _index)
00420     {
00421         MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ItemBox::setIndexSelected");
00422         if (_index == mIndexSelect) return;
00423 
00424         size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
00425 
00426         // сбрасываем старое выделение
00427         if (mIndexSelect != ITEM_NONE)
00428         {
00429             size_t index = mIndexSelect;
00430             mIndexSelect = ITEM_NONE;
00431 
00432             if ((index >= start) && (index < (start + mVectorItems.size())))
00433             {
00434                 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00435                 requestDrawItem(this, mVectorItems[index - start], data);
00436             }
00437         }
00438 
00439         mIndexSelect = _index;
00440         if (mIndexSelect != ITEM_NONE)
00441         {
00442             if ((_index >= start) && (_index < (start + mVectorItems.size())))
00443             {
00444                 IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00445                 requestDrawItem(this, mVectorItems[_index - start], data);
00446             }
00447         }
00448 
00449     }
00450 
00451     void ItemBox::notifyMouseButtonDoubleClick(Widget* _sender)
00452     {
00453         size_t index = getIndexByWidget(_sender);
00454 
00455         eventSelectItemAccept(this, index);
00456     }
00457 
00458     void ItemBox::setVerticalAlignment(bool _vert)
00459     {
00460         if (mAlignVert == _vert)
00461             return;
00462         mAlignVert = _vert;
00463 
00464         mCountItemInLine = -1;
00465         updateFromResize();
00466     }
00467 
00468     void ItemBox::notifyKeyButtonPressed(Widget* _sender, KeyCode _key, Char _char)
00469     {
00470         eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyPressed, _key, _char));
00471     }
00472 
00473     void ItemBox::notifyKeyButtonReleased(Widget* _sender, KeyCode _key)
00474     {
00475         eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyReleased, _key));
00476     }
00477 
00478     size_t ItemBox::getIndexByWidget(Widget* _widget)
00479     {
00480         MYGUI_ASSERT(_widget, "ItemBox::getIndexByWidget : Widget == nullptr");
00481         if (_widget == _getClientWidget()) return ITEM_NONE;
00482         MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ItemBox::getIndexByWidget : Widget is not child");
00483 
00484         size_t index = calcIndexByWidget(_widget);
00485         MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::getIndexByWidget");
00486 
00487         return index;
00488     }
00489 
00490     size_t ItemBox::_getContainerIndex(const IntPoint& _point)
00491     {
00492         for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
00493         {
00494             if ((*iter)->getVisible())
00495             {
00496                 if ((*iter)->getAbsoluteRect().inside(_point))
00497                 {
00498                     return getIndexByWidget(*iter);
00499                 }
00500             }
00501         }
00502         return ITEM_NONE;
00503     }
00504 
00505     void ItemBox::_resetContainer(bool _update)
00506     {
00507         // обязательно у базового
00508         Base::_resetContainer(_update);
00509 
00510         if ( ! _update)
00511         {
00512             WidgetManager& instance = WidgetManager::getInstance();
00513             for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
00514             {
00515                 instance.unlinkFromUnlinkers(*iter);
00516             }
00517         }
00518     }
00519 
00520     Widget* ItemBox::getWidgetByIndex(size_t _index)
00521     {
00522         for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
00523         {
00524             if ((*iter)->getVisible())
00525             {
00526                 size_t index = getIndexByWidget(*iter);
00527 
00528                 if (index == _index) return (*iter);
00529             }
00530         }
00531         return nullptr;
00532     }
00533 
00534     void ItemBox::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00535     {
00536         Base::onMouseButtonPressed(_left, _top, _id);
00537     }
00538 
00539     void ItemBox::onMouseButtonReleased(int _left, int _top, MouseButton _id)
00540     {
00541         Base::onMouseButtonReleased(_left, _top, _id);
00542     }
00543 
00544     void ItemBox::onMouseDrag(int _left, int _top, MouseButton _id)
00545     {
00546         Base::onMouseDrag(_left, _top, _id);
00547     }
00548 
00549     void ItemBox::removeDropItems()
00550     {
00551         if (mItemDrag) mItemDrag->setVisible(false);
00552     }
00553 
00554     void ItemBox::updateDropItems()
00555     {
00556         if (nullptr == mItemDrag)
00557         {
00558             // спрашиваем размер иконок
00559             IntCoord coord;
00560 
00561             requestCoordItem(this, coord, true);
00562 
00563             mPointDragOffset = coord.point();
00564 
00565             // создаем и запрашиваем детей
00566             mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer);
00567             requestCreateWidgetItem(this, mItemDrag);
00568         }
00569 
00570         const IntPoint& point = InputManager::getInstance().getMousePosition();
00571 
00572         mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top);
00573         mItemDrag->setVisible(true);
00574     }
00575 
00576     void ItemBox::updateDropItemsState(const DDWidgetState& _state)
00577     {
00578         IBDrawItemInfo data;
00579         data.drop_accept = _state.accept;
00580         data.drop_refuse = _state.refuse;
00581 
00582         data.select = false;
00583         data.active = false;
00584 
00585         data.index = mDropSenderIndex;
00586         data.update = _state.update;
00587         data.drag = true;
00588 
00589         requestDrawItem(this, mItemDrag, data);
00590     }
00591 
00592     void ItemBox::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
00593     {
00594         mouseDrag(_id);
00595     }
00596 
00597     void ItemBox::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
00598     {
00599         mouseButtonPressed(_id);
00600 
00601         if ( MouseButton::Left == _id)
00602         {
00603             size_t old = mIndexSelect;
00604 
00605             if (_sender == _getClientWidget())
00606             {
00607                 // сбрасываем выделение
00608                 setIndexSelected(ITEM_NONE);
00609             }
00610             else
00611             {
00612                 // индекс отправителя
00613                 mDropSenderIndex = getIndexByWidget(_sender);
00614 
00615                 // выделенный елемент
00616                 setIndexSelected(mDropSenderIndex);
00617             }
00618 
00619             // смещение внутри виджета, куда кликнули мышкой
00620             mClickInWidget = InputManager::getInstance().getLastPressedPosition(MouseButton::Left) - _sender->getAbsolutePosition();
00621 
00622             // отсылаем событие
00623             eventMouseItemActivate(this, mIndexSelect);
00624             // смену позиции отсылаем только при реальном изменении
00625             if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect);
00626         }
00627 
00628         eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::MousePressed, _left, _top, _id));
00629     }
00630 
00631     void ItemBox::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id)
00632     {
00633         bool needEvent = !mStartDrop;
00634         mouseButtonReleased(_id);
00635 
00636         if (needEvent)
00637             eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::MouseReleased, _left, _top, _id));
00638     }
00639 
00640     void ItemBox::notifyRootMouseChangeFocus(Widget* _sender, bool _focus)
00641     {
00642         size_t index = calcIndexByWidget(_sender);
00643         if (_focus)
00644         {
00645             MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::notifyRootMouseChangeFocus");
00646 
00647             // сбрасываем старый
00648             if (mIndexActive != ITEM_NONE)
00649             {
00650                 size_t old_index = mIndexActive;
00651                 mIndexActive = ITEM_NONE;
00652                 IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00653                 requestDrawItem(this, mVectorItems[old_index - (mFirstVisibleIndex * mCountItemInLine)], data);
00654             }
00655 
00656             mIndexActive = index;
00657             IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00658             requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
00659         }
00660         else
00661         {
00662             // при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс
00663             // сбрасываем индекс, только если мы и есть актив
00664             if (index < mItemsInfo.size() && mIndexActive == index)
00665             {
00666                 mIndexActive = ITEM_NONE;
00667                 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
00668                 requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
00669             }
00670         }
00671     }
00672 
00673     void ItemBox::updateMetrics()
00674     {
00675         if (mAlignVert)
00676         {
00677             // колличество айтемов на одной строке
00678             mCountItemInLine = _getClientWidget()->getWidth() / mSizeItem.width;
00679         }
00680         else
00681         {
00682             // колличество айтемов на одной строке
00683             mCountItemInLine = _getClientWidget()->getHeight() / mSizeItem.height;
00684         }
00685 
00686         if (1 > mCountItemInLine) mCountItemInLine = 1;
00687 
00688         // колличество строк
00689         mCountLines = mItemsInfo.size() / mCountItemInLine;
00690         if (0 != (mItemsInfo.size() % mCountItemInLine)) mCountLines ++;
00691 
00692         if (mAlignVert)
00693         {
00694             mContentSize.width = (mSizeItem.width * mCountItemInLine);
00695             mContentSize.height = (mSizeItem.height * mCountLines);
00696         }
00697         else
00698         {
00699             mContentSize.width = (mSizeItem.width * mCountLines);
00700             mContentSize.height = (mSizeItem.height * mCountItemInLine);
00701         }
00702     }
00703 
00704     void ItemBox::notifyScrollChangePosition(ScrollBar* _sender, size_t _index)
00705     {
00706         if (_sender == mVScroll)
00707         {
00708             mContentPosition.top = (int)_index;
00709         }
00710         else if (_sender == mHScroll)
00711         {
00712             mContentPosition.left = (int)_index;
00713         }
00714 
00715         setContentPosition(mContentPosition);
00716     }
00717 
00718     void ItemBox::notifyMouseWheel(Widget* _sender, int _rel)
00719     {
00720         if (mAlignVert)
00721         {
00722             if (mContentSize.height <= 0)
00723                 return;
00724 
00725             int offset = mContentPosition.top;
00726             if (_rel < 0)
00727                 offset += mSizeItem.height;
00728             else
00729                 offset -= mSizeItem.height;
00730 
00731             if (mContentSize.height <= _getClientWidget()->getHeight())
00732                 offset = 0;
00733             else if (offset >= mContentSize.height - _getClientWidget()->getHeight())
00734                 offset = mContentSize.height - _getClientWidget()->getHeight();
00735             else if (offset < 0)
00736                 offset = 0;
00737 
00738             if (mContentPosition.top == offset)
00739                 return;
00740 
00741             // сбрасываем старую подсветку
00742             // так как при прокрутке, мышь может находиться над окном
00743             resetCurrentActiveItem();
00744 
00745             mContentPosition.top = offset;
00746         }
00747         else
00748         {
00749             if (mContentSize.width <= 0)
00750                 return;
00751 
00752             int offset = mContentPosition.left;
00753             if (_rel < 0)
00754                 offset += mSizeItem.width;
00755             else
00756                 offset -= mSizeItem.width;
00757 
00758             if (mContentSize.width <= _getClientWidget()->getWidth())
00759                 offset = 0;
00760             else if (offset >= mContentSize.width - _getClientWidget()->getWidth())
00761                 offset = mContentSize.width - _getClientWidget()->getWidth();
00762             else if (offset < 0)
00763                 offset = 0;
00764 
00765             if (mContentPosition.left == offset)
00766                 return;
00767 
00768             // сбрасываем старую подсветку
00769             // так как при прокрутке, мышь может находиться над окном
00770             resetCurrentActiveItem();
00771 
00772             mContentPosition.left = offset;
00773         }
00774 
00775         setContentPosition(mContentPosition);
00776 
00777         // заново ищем и подсвечиваем айтем
00778         if (!mNeedDrop)
00779             findCurrentActiveItem();
00780 
00781         if (nullptr != mVScroll)
00782             mVScroll->setScrollPosition(mContentPosition.top);
00783         if (nullptr != mHScroll)
00784             mHScroll->setScrollPosition(mContentPosition.left);
00785     }
00786 
00787     void ItemBox::setContentPosition(const IntPoint& _point)
00788     {
00789         mContentPosition = _point;
00790 
00791         int old = mFirstVisibleIndex;
00792 
00793         if (mAlignVert)
00794         {
00795             mFirstVisibleIndex = mContentPosition.top / mSizeItem.height;
00796             mFirstOffsetIndex = mContentPosition.top % mSizeItem.height;
00797         }
00798         else
00799         {
00800             mFirstVisibleIndex = mContentPosition.left / mSizeItem.width;
00801             mFirstOffsetIndex = mContentPosition.left % mSizeItem.width;
00802         }
00803 
00804         _updateAllVisible(old != mFirstVisibleIndex);
00805         _resetContainer(true);
00806     }
00807 
00808     void ItemBox::redrawAllItems()
00809     {
00810         _updateAllVisible(true);
00811     }
00812 
00813     void ItemBox::resetDrag()
00814     {
00815         endDrop(true);
00816     }
00817 
00818     size_t ItemBox::calcIndexByWidget(Widget* _widget)
00819     {
00820         return *_widget->_getInternalData<size_t>() + (mFirstVisibleIndex * mCountItemInLine);
00821     }
00822 
00823     IntSize ItemBox::getContentSize()
00824     {
00825         return mContentSize;
00826     }
00827 
00828     IntPoint ItemBox::getContentPosition()
00829     {
00830         return mContentPosition;
00831     }
00832 
00833     IntSize ItemBox::getViewSize()
00834     {
00835         return _getClientWidget()->getSize();
00836     }
00837 
00838     void ItemBox::eraseContent()
00839     {
00840         updateMetrics();
00841     }
00842 
00843     size_t ItemBox::getHScrollPage()
00844     {
00845         return mSizeItem.width;
00846     }
00847 
00848     size_t ItemBox::getVScrollPage()
00849     {
00850         return mSizeItem.height;
00851     }
00852 
00853     Align ItemBox::getContentAlign()
00854     {
00855         return Align::Default;
00856     }
00857 
00858     IntRect ItemBox::_getClientAbsoluteRect()
00859     {
00860         return _getClientWidget()->getAbsoluteRect();
00861     }
00862 
00863     Widget* ItemBox::_getClientWidget()
00864     {
00865         return mClient == nullptr ? this : mClient;
00866     }
00867 
00868     size_t ItemBox::getItemCount() const
00869     {
00870         return mItemsInfo.size();
00871     }
00872 
00873     void ItemBox::addItem(Any _data)
00874     {
00875         insertItemAt(ITEM_NONE, _data);
00876     }
00877 
00878     size_t ItemBox::getIndexSelected() const
00879     {
00880         return mIndexSelect;
00881     }
00882 
00883     void ItemBox::clearIndexSelected()
00884     {
00885         setIndexSelected(ITEM_NONE);
00886     }
00887 
00888     void ItemBox::clearItemDataAt(size_t _index)
00889     {
00890         setItemDataAt(_index, Any::Null);
00891     }
00892 
00893     bool ItemBox::getVerticalAlignment() const
00894     {
00895         return mAlignVert;
00896     }
00897 
00898     Widget* ItemBox::getWidgetDrag()
00899     {
00900         return mItemDrag;
00901     }
00902 
00903     void ItemBox::setPosition(int _left, int _top)
00904     {
00905         setPosition(IntPoint(_left, _top));
00906     }
00907 
00908     void ItemBox::setSize(int _width, int _height)
00909     {
00910         setSize(IntSize(_width, _height));
00911     }
00912 
00913     void ItemBox::setCoord(int _left, int _top, int _width, int _height)
00914     {
00915         setCoord(IntCoord(_left, _top, _width, _height));
00916     }
00917 
00918     void ItemBox::setPropertyOverride(const std::string& _key, const std::string& _value)
00919     {
00921         if (_key == "VerticalAlignment")
00922             setVerticalAlignment(utility::parseValue<bool>(_value));
00923 
00924         else
00925         {
00926             Base::setPropertyOverride(_key, _value);
00927             return;
00928         }
00929 
00930         eventChangeProperty(this, _key, _value);
00931     }
00932 
00933     void ItemBox::setViewOffset(const IntPoint& _value)
00934     {
00935         if (mAlignVert)
00936         {
00937             if (mContentSize.height <= 0)
00938                 return;
00939 
00940             int offset = _value.top;
00941 
00942             if (mContentSize.height <= _getClientWidget()->getHeight())
00943                 offset = 0;
00944             else if (offset >= mContentSize.height - _getClientWidget()->getHeight())
00945                 offset = mContentSize.height - _getClientWidget()->getHeight();
00946             else if (offset < 0)
00947                 offset = 0;
00948 
00949             if (mContentPosition.top == offset)
00950                 return;
00951 
00952             // сбрасываем старую подсветку
00953             // так как при прокрутке, мышь может находиться над окном
00954             resetCurrentActiveItem();
00955 
00956             mContentPosition.top = offset;
00957         }
00958         else
00959         {
00960             if (mContentSize.width <= 0)
00961                 return;
00962 
00963             int offset = _value.left;
00964 
00965             if (mContentSize.width <= _getClientWidget()->getWidth())
00966                 offset = 0;
00967             else if (offset >= mContentSize.width - _getClientWidget()->getWidth())
00968                 offset = mContentSize.width - _getClientWidget()->getWidth();
00969             else if (offset < 0)
00970                 offset = 0;
00971 
00972             if (mContentPosition.left == offset)
00973                 return;
00974 
00975             // сбрасываем старую подсветку
00976             // так как при прокрутке, мышь может находиться над окном
00977             resetCurrentActiveItem();
00978 
00979             mContentPosition.left = offset;
00980         }
00981 
00982         setContentPosition(mContentPosition);
00983 
00984         // заново ищем и подсвечиваем айтем
00985         if (!mNeedDrop)
00986             findCurrentActiveItem();
00987 
00988         if (nullptr != mVScroll)
00989             mVScroll->setScrollPosition(mContentPosition.top);
00990         if (nullptr != mHScroll)
00991             mHScroll->setScrollPosition(mContentPosition.left);
00992     }
00993 
00994     IntPoint ItemBox::getViewOffset()
00995     {
00996         return getContentPosition();
00997     }
00998 
00999     void ItemBox::onKeyButtonPressed(KeyCode _key, Char _char)
01000     {
01001         Base::onKeyButtonPressed(_key, _char);
01002 
01003         eventNotifyItem(this, IBNotifyItemData(ITEM_NONE, IBNotifyItemData::KeyPressed, _key, _char));
01004     }
01005 
01006     void ItemBox::onKeyButtonReleased(KeyCode _key)
01007     {
01008         Base::onKeyButtonReleased(_key);
01009 
01010         eventNotifyItem(this, IBNotifyItemData(ITEM_NONE, IBNotifyItemData::KeyReleased, _key));
01011     }
01012 
01013 } // namespace MyGUI