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