1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-23 20:23:54 +00:00
openmw/extern/mygui_3.0.1/MyGUIEngine/src/MyGUI_ItemBox.cpp
2010-07-08 00:23:28 +02:00

905 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
@file
@author Albert Semenov
@date 11/2007
@module
*/
/*
This file is part of MyGUI.
MyGUI is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
MyGUI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_ItemBox.h"
#include "MyGUI_Button.h"
#include "MyGUI_VScroll.h"
#include "MyGUI_HScroll.h"
#include "MyGUI_ResourceSkin.h"
#include "MyGUI_InputManager.h"
#include "MyGUI_Gui.h"
#include "MyGUI_WidgetTranslate.h"
#include "MyGUI_WidgetManager.h"
namespace MyGUI
{
ItemBox::ItemBox() :
mCountItemInLine(0),
mCountLines(0),
mFirstVisibleIndex(0),
mFirstOffsetIndex(0),
mIndexSelect(ITEM_NONE),
mIndexActive(ITEM_NONE),
mIndexAccept(ITEM_NONE),
mIndexRefuse(ITEM_NONE),
mIsFocus(false),
mItemDrag(nullptr),
mAlignVert(true)
{
mChangeContentByResize = true;
}
void ItemBox::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
{
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
initialiseWidgetSkin(_info);
}
ItemBox::~ItemBox()
{
shutdownWidgetSkin();
}
void ItemBox::baseChangeWidgetSkin(ResourceSkin* _info)
{
shutdownWidgetSkin();
Base::baseChangeWidgetSkin(_info);
initialiseWidgetSkin(_info);
}
void ItemBox::initialiseWidgetSkin(ResourceSkin* _info)
{
// нам нужен фокус клавы
mNeedKeyFocus = true;
mDragLayer = "DragAndDrop";
const MapString& properties = _info->getProperties();
if (!properties.empty())
{
MapString::const_iterator iter = properties.find("AlignVert");
if (iter != properties.end()) mAlignVert = utility::parseBool(iter->second);
iter = properties.find("DragLayer");
if (iter != properties.end()) mDragLayer = iter->second;
}
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
{
if (*(*iter)->_getInternalData<std::string>() == "VScroll")
{
MYGUI_DEBUG_ASSERT( ! mVScroll, "widget already assigned");
mVScroll = (*iter)->castType<VScroll>();
mVScroll->eventScrollChangePosition = newDelegate(this, &ItemBox::notifyScrollChangePosition);
}
if (*(*iter)->_getInternalData<std::string>() == "HScroll")
{
MYGUI_DEBUG_ASSERT( ! mHScroll, "widget already assigned");
mHScroll = (*iter)->castType<HScroll>();
mHScroll->eventScrollChangePosition = newDelegate(this, &ItemBox::notifyScrollChangePosition);
}
else if (*(*iter)->_getInternalData<std::string>() == "Client")
{
MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned");
mWidgetClient = (*iter);
mWidgetClient->eventMouseWheel = newDelegate(this, &ItemBox::notifyMouseWheel);
mWidgetClient->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMouseButtonPressed);
mClient = mWidgetClient;
}
}
// сли нет скрола, то клиенская зона не обязательно
//MYGUI_ASSERT(nullptr != mWidgetClient, "Child Widget Client not found in skin (ItemBox must have Client) skin ='" << _info->getSkinName() << "'");
// подписываем клиент для драгэндропа
if (mWidgetClient != nullptr)
mWidgetClient->_requestGetContainer = newDelegate(this, &ItemBox::_requestGetContainer);
requestItemSize();
updateScrollSize();
updateScrollPosition();
}
void ItemBox::shutdownWidgetSkin()
{
mVScroll = nullptr;
mHScroll = nullptr;
mClient = nullptr;
mWidgetClient = nullptr;
}
void ItemBox::setPosition(const IntPoint& _point)
{
Base::setPosition(_point);
}
void ItemBox::setSize(const IntSize& _size)
{
Base::setSize(_size);
updateFromResize();
}
void ItemBox::setCoord(const IntCoord& _coord)
{
Base::setCoord(_coord);
updateFromResize();
}
void ItemBox::requestItemSize()
{
IntCoord coord(0, 0, 1, 1);
// спрашиваем размер иконок
requestCoordItem(this, coord, false);
mSizeItem = coord.size();
MYGUI_ASSERT((mSizeItem.width > 0 && mSizeItem.height > 0), "(mSizeItem.width > 0 && mSizeItem.height > 0) at requestCoordWidgetItem");
}
void ItemBox::updateFromResize()
{
requestItemSize();
updateScrollSize();
updateScrollPosition();
_updateAllVisible(true);
_resetContainer(true);
}
void ItemBox::_updateAllVisible(bool _redraw)
{
int count_visible = 0;
if (mAlignVert)
{
count_visible = (_getClientWidget()->getHeight() / mSizeItem.height) + 2;
}
else
{
count_visible = (_getClientWidget()->getWidth() / mSizeItem.width) + 2;
}
size_t start = (mFirstVisibleIndex * mCountItemInLine);
size_t count = (count_visible * mCountItemInLine) + start;
size_t index = 0;
for (size_t pos = start; pos<count; ++pos, ++index)
{
// дальше нет айтемов
if (pos >= mItemsInfo.size()) break;
Widget* item = getItemWidget(index);
if (mAlignVert)
{
item->setPosition(((int)index % mCountItemInLine) * mSizeItem.width - mContentPosition.left,
(((int)index / mCountItemInLine) * mSizeItem.height) - mFirstOffsetIndex);
}
else
{
item->setPosition((((int)index / mCountItemInLine) * mSizeItem.width) - mFirstOffsetIndex,
((int)index % mCountItemInLine) * mSizeItem.height - mContentPosition.top);
}
item->setSize(mSizeItem);
item->setVisible(true);
if (_redraw)
{
IBDrawItemInfo data(pos, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
requestDrawItem(this, item, data);
}
}
// все виджеты еще есть, то их надо бы скрыть
while (index < mVectorItems.size())
{
mVectorItems[index]->setVisible(false);
index ++;
}
}
Widget* ItemBox::getItemWidget(size_t _index)
{
// еще нет такого виджета, нуно создать
if (_index == mVectorItems.size())
{
requestItemSize();
Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(0, 0, mSizeItem.width, mSizeItem.height), Align::Default);
// вызываем запрос на создание виджета
requestCreateWidgetItem(this, item);
item->eventMouseWheel = newDelegate(this, &ItemBox::notifyMouseWheel);
item->eventRootMouseChangeFocus = newDelegate(this, &ItemBox::notifyRootMouseChangeFocus);
item->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMouseButtonPressed);
item->eventMouseButtonReleased = newDelegate(this, &ItemBox::notifyMouseButtonReleased);
item->eventMouseButtonDoubleClick = newDelegate(this, &ItemBox::notifyMouseButtonDoubleClick);
item->eventMouseDrag = newDelegate(this, &ItemBox::notifyMouseDrag);
item->_requestGetContainer = newDelegate(this, &ItemBox::_requestGetContainer);
item->eventKeyButtonPressed = newDelegate(this, &ItemBox::notifyKeyButtonPressed);
item->eventKeyButtonReleased = newDelegate(this, &ItemBox::notifyKeyButtonReleased);
item->_setInternalData((size_t)mVectorItems.size());
mVectorItems.push_back(item);
}
// запрашивать только последовательно
MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ItemBox::getItemWidget");
return mVectorItems[_index];
}
void ItemBox::onMouseWheel(int _rel)
{
notifyMouseWheel(nullptr, _rel);
Base::onMouseWheel(_rel);
}
void ItemBox::onKeySetFocus(Widget* _old)
{
mIsFocus = true;
setState("pushed");
Base::onKeySetFocus(_old);
}
void ItemBox::onKeyLostFocus(Widget* _new)
{
mIsFocus = false;
setState("normal");
Base::onKeyLostFocus(_new);
}
void ItemBox::resetCurrentActiveItem()
{
// сбрасываем старую подсветку
if (mIndexActive != ITEM_NONE)
{
size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
size_t index = mIndexActive;
mIndexActive = ITEM_NONE;
// если видим, то обновляем
if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size())))
{
IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[mIndexActive - start], data);
}
}
}
void ItemBox::findCurrentActiveItem()
{
MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()");
const IntPoint& point = InputManager::getInstance().getMousePositionByLayer();
// сначала проверяем клиентскую зону
const IntRect& rect = _getClientAbsoluteRect();
if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom))
{
return;
}
for (size_t pos=0; pos<mVectorItems.size(); ++pos)
{
Widget* item = mVectorItems[pos];
const IntRect& abs_rect = item->getAbsoluteRect();
if ((point.left>= abs_rect.left) && (point.left <= abs_rect.right) && (point.top>= abs_rect.top) && (point.top <= abs_rect.bottom))
{
size_t index = calcIndexByWidget(item);
// при переборе индекс может быть больше, так как может создасться сколько угодно
if (index < mItemsInfo.size())
{
mIndexActive = index;
IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, item, data);
}
break;
}
}
}
void ItemBox::_requestGetContainer(Widget* _sender, Widget*& _container, size_t& _index)
{
if (_sender == _getClientWidget())
{
_container = this;
_index = ITEM_NONE;
}
else
{
size_t index = calcIndexByWidget(_sender);
if (index < mItemsInfo.size())
{
_container = this;
_index = index;
}
}
}
void ItemBox::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
{
if (_index == ITEM_NONE) return;
MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::_setContainerItemInfo");
mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE;
mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE;
size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
if ((_index >= start) && (_index < (start + mVectorItems.size())))
{
IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[_index - start], data);
}
}
void ItemBox::setItemDataAt(size_t _index, Any _data)
{
MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::setItemData");
mItemsInfo[_index].data = _data;
size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
if ((_index >= start) && (_index < (start + mVectorItems.size())))
{
IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
requestDrawItem(this, mVectorItems[_index - start], data);
}
_resetContainer(true);
}
void ItemBox::insertItemAt(size_t _index, Any _data)
{
MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ItemBox::insertItemAt");
if (_index == ITEM_NONE) _index = mItemsInfo.size();
_resetContainer(false);
resetCurrentActiveItem();
mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data));
// расчитываем новый индекс выделения
if (mIndexSelect != ITEM_NONE)
{
if (mIndexSelect >= _index)
{
mIndexSelect ++;
}
}
updateScrollSize();
updateScrollPosition();
findCurrentActiveItem();
_updateAllVisible(true);
}
void ItemBox::removeItemAt(size_t _index)
{
MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::removeItemAt");
_resetContainer(false);
resetCurrentActiveItem();
mItemsInfo.erase(mItemsInfo.begin() + _index);
// расчитываем новый индекс выделения
if (mIndexSelect != ITEM_NONE)
{
if (mItemsInfo.empty())
{
mIndexSelect = ITEM_NONE;
}
else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size()))
{
mIndexSelect --;
}
}
updateScrollSize();
updateScrollPosition();
findCurrentActiveItem();
_updateAllVisible(true);
}
void ItemBox::removeAllItems()
{
if (0 == mItemsInfo.size()) return;
_resetContainer(false);
mItemsInfo.clear();
mIndexSelect = ITEM_NONE;
mIndexActive = ITEM_NONE;
updateScrollSize();
updateScrollPosition();
_updateAllVisible(true);
}
void ItemBox::redrawItemAt(size_t _index)
{
MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::redrawItemAt");
size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
if ((_index >= start) && (_index < (start + mVectorItems.size())))
{
IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
requestDrawItem(this, mVectorItems[_index - start], data);
}
}
void ItemBox::setIndexSelected(size_t _index)
{
MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ItemBox::setIndexSelected");
if (_index == mIndexSelect) return;
size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
// сбрасываем старое выделение
if (mIndexSelect != ITEM_NONE)
{
size_t index = mIndexSelect;
mIndexSelect = ITEM_NONE;
if ((index >= start) && (index < (start + mVectorItems.size())))
{
IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[index - start], data);
}
}
mIndexSelect = _index;
if (mIndexSelect != ITEM_NONE)
{
if ((_index >= start) && (_index < (start + mVectorItems.size())))
{
IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[_index - start], data);
}
}
}
void ItemBox::notifyMouseButtonDoubleClick(Widget* _sender)
{
size_t index = getIndexByWidget(_sender);
eventSelectItemAccept(this, index);
}
void ItemBox::setItemBoxAlignVert(bool _vert)
{
if (mAlignVert == _vert) return;
mAlignVert = _vert;
mCountItemInLine = -1;
updateFromResize();
}
void ItemBox::notifyKeyButtonPressed(Widget* _sender, KeyCode _key, Char _char)
{
eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyPressed, _key, _char));
}
void ItemBox::notifyKeyButtonReleased(Widget* _sender, KeyCode _key)
{
eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyReleased, _key));
}
size_t ItemBox::getIndexByWidget(Widget* _widget)
{
MYGUI_ASSERT(_widget, "ItemBox::getIndexByWidget : Widget == nullptr");
if (_widget == _getClientWidget()) return ITEM_NONE;
MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ItemBox::getIndexByWidget : Widget is not child");
size_t index = calcIndexByWidget(_widget);
MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::getIndexByWidget");
return index;
}
size_t ItemBox::_getContainerIndex(const IntPoint& _point)
{
for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
{
if ((*iter)->isVisible())
{
if ((*iter)->getAbsoluteRect().inside(_point))
{
return getIndexByWidget(*iter);
}
}
}
return ITEM_NONE;
}
void ItemBox::_resetContainer(bool _update)
{
// обязательно у базового
Base::_resetContainer(_update);
if ( ! _update)
{
WidgetManager& instance = WidgetManager::getInstance();
for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
{
instance.unlinkFromUnlinkers(*iter);
}
}
}
Widget* ItemBox::getWidgetByIndex(size_t _index)
{
for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
{
if ((*iter)->isVisible())
{
size_t index = getIndexByWidget(*iter);
if (index == _index) return (*iter);
}
}
return nullptr;
}
void ItemBox::onMouseButtonPressed(int _left, int _top, MouseButton _id)
{
Base::onMouseButtonPressed(_left, _top, _id);
}
void ItemBox::onMouseButtonReleased(int _left, int _top, MouseButton _id)
{
Base::onMouseButtonReleased(_left, _top, _id);
}
void ItemBox::onMouseDrag(int _left, int _top)
{
Base::onMouseDrag(_left, _top);
}
void ItemBox::removeDropItems()
{
if (mItemDrag) mItemDrag->setVisible(false);
}
void ItemBox::updateDropItems()
{
if (nullptr == mItemDrag)
{
// спрашиваем размер иконок
IntCoord coord;
requestCoordItem(this, coord, true);
mPointDragOffset = coord.point();
// создаем и запрашиваем детей
mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer);
requestCreateWidgetItem(this, mItemDrag);
}
const IntPoint& point = InputManager::getInstance().getMousePosition();
mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top);
mItemDrag->setVisible(true);
}
void ItemBox::updateDropItemsState(const DDWidgetState& _state)
{
IBDrawItemInfo data;
data.drop_accept = _state.accept;
data.drop_refuse = _state.refuse;
data.select = false;
data.active = false;
data.index = mDropSenderIndex;
data.update = _state.update;
data.drag = true;
requestDrawItem(this, mItemDrag, data);
}
void ItemBox::notifyMouseDrag(Widget* _sender, int _left, int _top)
{
mouseDrag();
}
void ItemBox::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
{
mouseButtonPressed(_id);
if ( MouseButton::Left == _id)
{
size_t old = mIndexSelect;
if (_sender == _getClientWidget())
{
// сбрасываем выделение
setIndexSelected(ITEM_NONE);
}
else
{
// индекс отправителя
mDropSenderIndex = getIndexByWidget(_sender);
// выделенный елемент
setIndexSelected(mDropSenderIndex);
}
// смещение внутри виджета, куда кликнули мышкой
mClickInWidget = InputManager::getInstance().getLastLeftPressed() - _sender->getAbsolutePosition();
// отсылаем событие
eventMouseItemActivate(this, mIndexSelect);
// смену позиции отсылаем только при реальном изменении
if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect);
}
eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::MousePressed, _left, _top, _id));
}
void ItemBox::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id)
{
mouseButtonReleased(_id);
size_t index = calcIndexByWidget(_sender);
// солличество айтемов может измениться
if (index >= getItemCount()) return;
eventNotifyItem(this, IBNotifyItemData(index, IBNotifyItemData::MouseReleased, _left, _top, _id));
}
void ItemBox::notifyRootMouseChangeFocus(Widget* _sender, bool _focus)
{
size_t index = calcIndexByWidget(_sender);
if (_focus)
{
MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::notifyRootMouseChangeFocus");
// сбрасываем старый
if (mIndexActive != ITEM_NONE)
{
size_t old_index = mIndexActive;
mIndexActive = ITEM_NONE;
IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[old_index - (mFirstVisibleIndex * mCountItemInLine)], data);
}
mIndexActive = index;
IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
}
else
{
// при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс
// сбрасываем индекс, только если мы и есть актив
if (index < mItemsInfo.size() && mIndexActive == index)
{
mIndexActive = ITEM_NONE;
IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
}
}
}
void ItemBox::updateMetrics()
{
if (mAlignVert)
{
// колличество айтемов на одной строке
mCountItemInLine = _getClientWidget()->getWidth() / mSizeItem.width;
}
else
{
// колличество айтемов на одной строке
mCountItemInLine = _getClientWidget()->getHeight() / mSizeItem.height;
}
if (1 > mCountItemInLine) mCountItemInLine = 1;
// колличество строк
mCountLines = mItemsInfo.size() / mCountItemInLine;
if (0 != (mItemsInfo.size() % mCountItemInLine)) mCountLines ++;
if (mAlignVert)
{
mContentSize.width = (mSizeItem.width * mCountItemInLine);
mContentSize.height = (mSizeItem.height * mCountLines);
}
else
{
mContentSize.width = (mSizeItem.width * mCountLines);
mContentSize.height = (mSizeItem.height * mCountItemInLine);
}
}
void ItemBox::notifyScrollChangePosition(VScroll* _sender, size_t _index)
{
if (_sender == mVScroll)
{
mContentPosition.top = (int)_index;
}
else if (_sender == mHScroll)
{
mContentPosition.left = (int)_index;
}
setContentPosition(mContentPosition);
}
void ItemBox::notifyMouseWheel(Widget* _sender, int _rel)
{
if (mAlignVert)
{
if (mContentSize.height <= 0) return;
int offset = mContentPosition.top;
if (_rel < 0) offset += mSizeItem.height;
else offset -= mSizeItem.height;
if (offset >= mContentSize.height - _getClientWidget()->getHeight()) offset = mContentSize.height - _getClientWidget()->getHeight();
else if (offset < 0) offset = 0;
if (mContentPosition.top == offset) return;
// сбрасываем старую подсветку
// так как при прокрутке, мышь может находиться над окном
resetCurrentActiveItem();
mContentPosition.top = offset;
}
else
{
if (mContentSize.width <= 0) return;
int offset = mContentPosition.left;
if (_rel < 0) offset += mSizeItem.width;
else offset -= mSizeItem.width;
if (offset >= mContentSize.width - _getClientWidget()->getWidth()) offset = mContentSize.width - _getClientWidget()->getWidth();
else if (offset < 0) offset = 0;
if (mContentPosition.left == offset) return;
// сбрасываем старую подсветку
// так как при прокрутке, мышь может находиться над окном
resetCurrentActiveItem();
mContentPosition.left = offset;
}
setContentPosition(mContentPosition);
// заново ищем и подсвечиваем айтем
if (!mNeedDrop)
findCurrentActiveItem();
if (nullptr != mVScroll) mVScroll->setScrollPosition(mContentPosition.top);
if (nullptr != mHScroll) mHScroll->setScrollPosition(mContentPosition.left);
}
void ItemBox::setContentPosition(const IntPoint& _point)
{
mContentPosition = _point;
int old = mFirstVisibleIndex;
if (mAlignVert)
{
mFirstVisibleIndex = mContentPosition.top / mSizeItem.height;
mFirstOffsetIndex = mContentPosition.top % mSizeItem.height;
}
else
{
mFirstVisibleIndex = mContentPosition.left / mSizeItem.width;
mFirstOffsetIndex = mContentPosition.left % mSizeItem.width;
}
_updateAllVisible(old != mFirstVisibleIndex);
_resetContainer(true);
}
void ItemBox::redrawAllItems()
{
_updateAllVisible(true);
}
void ItemBox::resetDrag()
{
endDrop(true);
}
size_t ItemBox::calcIndexByWidget(Widget* _widget)
{
return *_widget->_getInternalData<size_t>() + (mFirstVisibleIndex * mCountItemInLine);
}
IntSize ItemBox::getContentSize()
{
return mContentSize;
}
IntPoint ItemBox::getContentPosition()
{
return mContentPosition;
}
IntSize ItemBox::getViewSize() const
{
return _getClientWidget()->getSize();
}
void ItemBox::eraseContent()
{
updateMetrics();
}
size_t ItemBox::getHScrollPage()
{
return mSizeItem.width;
}
size_t ItemBox::getVScrollPage()
{
return mSizeItem.height;
}
Align ItemBox::getContentAlign()
{
return Align::Default;
}
IntRect ItemBox::_getClientAbsoluteRect()
{
return _getClientWidget()->getAbsoluteRect();
}
Widget* ItemBox::_getClientWidget()
{
return mWidgetClient == nullptr ? this : mWidgetClient;
}
const Widget* ItemBox::_getClientWidget() const
{
return mWidgetClient == nullptr ? this : mWidgetClient;
}
} // namespace MyGUI