forked from teamnwah/openmw-tes3coop
312 lines
7.8 KiB
C++
312 lines
7.8 KiB
C++
|
/*!
|
|||
|
@file
|
|||
|
@author Albert Semenov
|
|||
|
@date 10/2008
|
|||
|
@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_DDContainer.h"
|
|||
|
#include "MyGUI_InputManager.h"
|
|||
|
#include "MyGUI_LayerManager.h"
|
|||
|
|
|||
|
namespace MyGUI
|
|||
|
{
|
|||
|
|
|||
|
DDContainer::DDContainer() :
|
|||
|
mDropResult(false),
|
|||
|
mNeedDrop(false),
|
|||
|
mStartDrop(false),
|
|||
|
mOldDrop(nullptr),
|
|||
|
mCurrentSender(nullptr),
|
|||
|
mDropSenderIndex(ITEM_NONE),
|
|||
|
mDropItem(nullptr),
|
|||
|
mNeedDragDrop(false),
|
|||
|
mReseiverContainer(nullptr)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::_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);
|
|||
|
}
|
|||
|
|
|||
|
DDContainer::~DDContainer()
|
|||
|
{
|
|||
|
shutdownWidgetSkin();
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::baseChangeWidgetSkin(ResourceSkin* _info)
|
|||
|
{
|
|||
|
shutdownWidgetSkin();
|
|||
|
Base::baseChangeWidgetSkin(_info);
|
|||
|
initialiseWidgetSkin(_info);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::initialiseWidgetSkin(ResourceSkin* _info)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::shutdownWidgetSkin()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::onMouseButtonPressed(int _left, int _top, MouseButton _id)
|
|||
|
{
|
|||
|
// смещение внутри виджета, куда кликнули мышкой
|
|||
|
mClickInWidget = InputManager::getInstance().getLastLeftPressed() - getAbsolutePosition();
|
|||
|
|
|||
|
mouseButtonPressed(_id);
|
|||
|
|
|||
|
Base::onMouseButtonPressed(_left, _top, _id);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::onMouseButtonReleased(int _left, int _top, MouseButton _id)
|
|||
|
{
|
|||
|
mouseButtonReleased(_id);
|
|||
|
|
|||
|
Base::onMouseButtonReleased(_left, _top, _id);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::onMouseDrag(int _left, int _top)
|
|||
|
{
|
|||
|
mouseDrag();
|
|||
|
|
|||
|
Base::onMouseDrag(_left, _top);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::mouseButtonPressed(MouseButton _id)
|
|||
|
{
|
|||
|
if (MouseButton::Left == _id)
|
|||
|
{
|
|||
|
// сбрасываем инфу для дропа
|
|||
|
mDropResult = false;
|
|||
|
mOldDrop = nullptr;
|
|||
|
mDropInfo.reset();
|
|||
|
mReseiverContainer = nullptr;
|
|||
|
|
|||
|
// сбрасываем, чтобы обновился дропный виджет
|
|||
|
mCurrentSender = nullptr;
|
|||
|
mStartDrop = false;
|
|||
|
|
|||
|
}
|
|||
|
// если нажата другая клавиша и был дроп то сбрасываем
|
|||
|
else
|
|||
|
{
|
|||
|
endDrop(true);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::mouseButtonReleased(MouseButton _id)
|
|||
|
{
|
|||
|
if (MouseButton::Left == _id)
|
|||
|
{
|
|||
|
endDrop(false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::mouseDrag()
|
|||
|
{
|
|||
|
// нужно ли обновить данные
|
|||
|
bool update = false;
|
|||
|
|
|||
|
// первый раз дропаем елемент
|
|||
|
if (!mStartDrop && mDropSenderIndex != ITEM_NONE)
|
|||
|
{
|
|||
|
mStartDrop = true;
|
|||
|
mNeedDrop = false;
|
|||
|
update = true;
|
|||
|
// запрос на нужность дропа по индексу
|
|||
|
mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
|
|||
|
mReseiverContainer = nullptr;
|
|||
|
|
|||
|
eventStartDrag(this, mDropInfo, mNeedDrop);
|
|||
|
|
|||
|
if (mNeedDrop)
|
|||
|
{
|
|||
|
eventChangeDDState(this, DDItemState::Start);
|
|||
|
setEnableToolTip(false);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// сбрасываем фокус мыши (не обязательно)
|
|||
|
InputManager::getInstance().resetMouseCaptureWidget();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// дроп не нужен
|
|||
|
if (!mNeedDrop)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// делаем запрос, над кем наша мыша
|
|||
|
const IntPoint& point = InputManager::getInstance().getMousePosition();
|
|||
|
Widget* item = LayerManager::getInstance().getWidgetFromPoint(point.left, point.top);
|
|||
|
|
|||
|
updateDropItems();
|
|||
|
|
|||
|
// если равно, значит уже спрашивали
|
|||
|
if (mOldDrop == item) return;
|
|||
|
mOldDrop = item;
|
|||
|
|
|||
|
// сбрасываем старую подсветку
|
|||
|
if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
|
|||
|
|
|||
|
mDropResult = false;
|
|||
|
mReseiverContainer = nullptr;
|
|||
|
Widget* receiver = nullptr;
|
|||
|
size_t receiver_index = ITEM_NONE;
|
|||
|
// есть виджет под нами
|
|||
|
if (item)
|
|||
|
{
|
|||
|
// делаем запрос на индекс по произвольному виджету
|
|||
|
item->_getContainer(receiver, receiver_index);
|
|||
|
// работаем только с контейнерами
|
|||
|
if (receiver && receiver->isType<DDContainer>())
|
|||
|
{
|
|||
|
// подписываемся на информацию о валидности дропа
|
|||
|
mReseiverContainer = static_cast<DDContainer*>(receiver);
|
|||
|
mReseiverContainer->_eventInvalideContainer = newDelegate(this, &DDContainer::notifyInvalideDrop);
|
|||
|
|
|||
|
// делаем запрос на возможность дропа
|
|||
|
mDropInfo.set(this, mDropSenderIndex, mReseiverContainer, receiver_index);
|
|||
|
|
|||
|
eventRequestDrop(this, mDropInfo, mDropResult);
|
|||
|
|
|||
|
// устанавливаем новую подсветку
|
|||
|
mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, true, mDropResult);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
|
|||
|
}
|
|||
|
}
|
|||
|
// нет виджета под нами
|
|||
|
else
|
|||
|
{
|
|||
|
mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
|
|||
|
}
|
|||
|
|
|||
|
DDItemState state;
|
|||
|
|
|||
|
DDWidgetState data(mDropSenderIndex);
|
|||
|
data.update = update;
|
|||
|
|
|||
|
if (receiver == nullptr)
|
|||
|
{
|
|||
|
data.accept = false;
|
|||
|
data.refuse = false;
|
|||
|
state = DDItemState::Miss;
|
|||
|
}
|
|||
|
else if (mDropResult)
|
|||
|
{
|
|||
|
data.accept = true;
|
|||
|
data.refuse = false;
|
|||
|
state = DDItemState::Accept;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
data.accept = false;
|
|||
|
data.refuse = true;
|
|||
|
state = DDItemState::Refuse;
|
|||
|
}
|
|||
|
|
|||
|
updateDropItemsState(data);
|
|||
|
|
|||
|
eventChangeDDState(this, state);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::endDrop(bool _reset)
|
|||
|
{
|
|||
|
if (mStartDrop)
|
|||
|
{
|
|||
|
removeDropItems();
|
|||
|
|
|||
|
// сбрасываем старую подсветку
|
|||
|
if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
|
|||
|
|
|||
|
if (_reset) mDropResult = false;
|
|||
|
eventDropResult(this, mDropInfo, mDropResult);
|
|||
|
eventChangeDDState(this, DDItemState::End);
|
|||
|
setEnableToolTip(true);
|
|||
|
|
|||
|
// сбрасываем инфу для дропа
|
|||
|
mStartDrop = false;
|
|||
|
mDropResult = false;
|
|||
|
mNeedDrop = false;
|
|||
|
mOldDrop = nullptr;
|
|||
|
mDropInfo.reset();
|
|||
|
mReseiverContainer = nullptr;
|
|||
|
mDropSenderIndex = ITEM_NONE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::removeDropItems()
|
|||
|
{
|
|||
|
mDropItem = nullptr;
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::updateDropItems()
|
|||
|
{
|
|||
|
|
|||
|
if (mDropItem == nullptr)
|
|||
|
{
|
|||
|
requestDragWidgetInfo(this, mDropItem, mDropDimension);
|
|||
|
}
|
|||
|
|
|||
|
const IntPoint& point = InputManager::getInstance().getMousePositionByLayer();
|
|||
|
|
|||
|
if (mDropItem)
|
|||
|
{
|
|||
|
mDropItem->setCoord(point.left - mClickInWidget.left + mDropDimension.left, point.top - mClickInWidget.top + mDropDimension.top, mDropDimension.width, mDropDimension.height);
|
|||
|
mDropItem->setVisible(true);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::updateDropItemsState(const DDWidgetState& _state)
|
|||
|
{
|
|||
|
eventUpdateDropState(this, mDropItem, _state);
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::notifyInvalideDrop(DDContainer* _sender)
|
|||
|
{
|
|||
|
mouseDrag();
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::_getContainer(Widget*& _container, size_t& _index)
|
|||
|
{
|
|||
|
_container = this;
|
|||
|
_index = ITEM_NONE;
|
|||
|
}
|
|||
|
|
|||
|
void DDContainer::setProperty(const std::string& _key, const std::string& _value)
|
|||
|
{
|
|||
|
if (_key == "DDContainer_NeedDragDrop") setNeedDragDrop(utility::parseValue<bool>(_value));
|
|||
|
else
|
|||
|
{
|
|||
|
Base::setProperty(_key, _value);
|
|||
|
return;
|
|||
|
}
|
|||
|
eventChangeProperty(this, _key, _value);
|
|||
|
}
|
|||
|
|
|||
|
} // namespace MyGUI
|