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