MyGUI 3.0.1

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