MyGUI  3.2.1
MyGUI_DDContainer.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_DDContainer.h"
00009 #include "MyGUI_InputManager.h"
00010 #include "MyGUI_LayerManager.h"
00011 
00012 namespace MyGUI
00013 {
00014 
00015     DDContainer::DDContainer() :
00016         mDropResult(false),
00017         mNeedDrop(false),
00018         mStartDrop(false),
00019         mOldDrop(nullptr),
00020         mCurrentSender(nullptr),
00021         mDropSenderIndex(ITEM_NONE),
00022         mDropItem(nullptr),
00023         mNeedDragDrop(false),
00024         mReseiverContainer(nullptr)
00025     {
00026     }
00027 
00028     void DDContainer::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00029     {
00030         // смещение внутри виджета, куда кликнули мышкой
00031         mClickInWidget = InputManager::getInstance().getLastPressedPosition(MouseButton::Left) - getAbsolutePosition();
00032 
00033         mouseButtonPressed(_id);
00034 
00035         Base::onMouseButtonPressed(_left, _top, _id);
00036     }
00037 
00038     void DDContainer::onMouseButtonReleased(int _left, int _top, MouseButton _id)
00039     {
00040         mouseButtonReleased(_id);
00041 
00042         Base::onMouseButtonReleased(_left, _top, _id);
00043     }
00044 
00045     void DDContainer::onMouseDrag(int _left, int _top, MouseButton _id)
00046     {
00047         mouseDrag(_id);
00048 
00049         Base::onMouseDrag(_left, _top, _id);
00050     }
00051 
00052     void DDContainer::mouseButtonPressed(MouseButton _id)
00053     {
00054         if (MouseButton::Left == _id)
00055         {
00056             // сбрасываем инфу для дропа
00057             mDropResult = false;
00058             mOldDrop = nullptr;
00059             mDropInfo.reset();
00060             mReseiverContainer = nullptr;
00061 
00062             // сбрасываем, чтобы обновился дропный виджет
00063             mCurrentSender = nullptr;
00064             mStartDrop = false;
00065 
00066         }
00067         // если нажата другая клавиша и был дроп то сбрасываем
00068         else
00069         {
00070             endDrop(true);
00071         }
00072     }
00073 
00074     void DDContainer::mouseButtonReleased(MouseButton _id)
00075     {
00076         if (MouseButton::Left == _id)
00077         {
00078             endDrop(false);
00079         }
00080     }
00081 
00082     void DDContainer::mouseDrag(MouseButton _id)
00083     {
00084         if (MouseButton::Left != _id)
00085             return;
00086 
00087         // нужно ли обновить данные
00088         bool update = false;
00089 
00090         // первый раз дропаем елемент
00091         if (!mStartDrop && mDropSenderIndex != ITEM_NONE)
00092         {
00093             mStartDrop = true;
00094             mNeedDrop = false;
00095             update = true;
00096             // запрос на нужность дропа по индексу
00097             mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00098             mReseiverContainer = nullptr;
00099 
00100             eventStartDrag(this, mDropInfo, mNeedDrop);
00101 
00102             if (mNeedDrop)
00103             {
00104                 eventChangeDDState(this, DDItemState::Start);
00105             }
00106             else
00107             {
00108                 // сбрасываем фокус мыши (не обязательно)
00109                 InputManager::getInstance().resetMouseCaptureWidget();
00110             }
00111         }
00112 
00113         // дроп не нужен
00114         if (!mNeedDrop)
00115         {
00116             return;
00117         }
00118 
00119         // делаем запрос, над кем наша мыша
00120         const IntPoint& point = InputManager::getInstance().getMousePosition();
00121         Widget* item = LayerManager::getInstance().getWidgetFromPoint(point.left, point.top);
00122 
00123         updateDropItems();
00124 
00125         // если равно, значит уже спрашивали
00126         if (mOldDrop == item) return;
00127         mOldDrop = item;
00128 
00129         // сбрасываем старую подсветку
00130         if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
00131 
00132         mDropResult = false;
00133         mReseiverContainer = nullptr;
00134         Widget* receiver = nullptr;
00135         size_t receiver_index = ITEM_NONE;
00136         // есть виджет под нами
00137         if (item)
00138         {
00139             // делаем запрос на индекс по произвольному виджету
00140             receiver = item->_getContainer();
00141             // работаем только с контейнерами
00142             if (receiver && receiver->isType<DDContainer>())
00143             {
00144                 receiver_index = receiver->_getItemIndex(item);
00145 
00146                 // подписываемся на информацию о валидности дропа
00147                 mReseiverContainer = static_cast<DDContainer*>(receiver);
00148                 mReseiverContainer->_eventInvalideContainer.clear();
00149                 mReseiverContainer->_eventInvalideContainer += newDelegate(this, &DDContainer::notifyInvalideDrop);
00150 
00151                 // делаем запрос на возможность дропа
00152                 mDropInfo.set(this, mDropSenderIndex, mReseiverContainer, receiver_index);
00153 
00154                 eventRequestDrop(this, mDropInfo, mDropResult);
00155 
00156                 // устанавливаем новую подсветку
00157                 mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, true, mDropResult);
00158             }
00159             else
00160             {
00161                 mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00162             }
00163         }
00164         // нет виджета под нами
00165         else
00166         {
00167             mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00168         }
00169 
00170         DDItemState state;
00171 
00172         DDWidgetState data(mDropSenderIndex);
00173         data.update = update;
00174 
00175         if (receiver == nullptr)
00176         {
00177             data.accept = false;
00178             data.refuse = false;
00179             state = DDItemState::Miss;
00180         }
00181         else if (mDropResult)
00182         {
00183             data.accept = true;
00184             data.refuse = false;
00185             state = DDItemState::Accept;
00186         }
00187         else
00188         {
00189             data.accept = false;
00190             data.refuse = true;
00191             state = DDItemState::Refuse;
00192         }
00193 
00194         updateDropItemsState(data);
00195 
00196         eventChangeDDState(this, state);
00197     }
00198 
00199     void DDContainer::endDrop(bool _reset)
00200     {
00201         if (mStartDrop)
00202         {
00203             removeDropItems();
00204 
00205             // сбрасываем старую подсветку
00206             if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
00207 
00208             if (_reset) mDropResult = false;
00209             eventDropResult(this, mDropInfo, mDropResult);
00210             eventChangeDDState(this, DDItemState::End);
00211 
00212             // сбрасываем инфу для дропа
00213             mStartDrop = false;
00214             mDropResult = false;
00215             mNeedDrop = false;
00216             mOldDrop = nullptr;
00217             mDropInfo.reset();
00218             mReseiverContainer = nullptr;
00219             mDropSenderIndex = ITEM_NONE;
00220         }
00221     }
00222 
00223     void DDContainer::removeDropItems()
00224     {
00225         mDropItem = nullptr;
00226     }
00227 
00228     void DDContainer::updateDropItems()
00229     {
00230 
00231         if (mDropItem == nullptr)
00232         {
00233             requestDragWidgetInfo(this, mDropItem, mDropDimension);
00234         }
00235 
00236         const IntPoint& point = InputManager::getInstance().getMousePositionByLayer();
00237 
00238         if (mDropItem)
00239         {
00240             mDropItem->setCoord(point.left - mClickInWidget.left + mDropDimension.left, point.top - mClickInWidget.top + mDropDimension.top, mDropDimension.width, mDropDimension.height);
00241             mDropItem->setVisible(true);
00242         }
00243     }
00244 
00245     void DDContainer::updateDropItemsState(const DDWidgetState& _state)
00246     {
00247         eventUpdateDropState(this, mDropItem, _state);
00248     }
00249 
00250     void DDContainer::notifyInvalideDrop(DDContainer* _sender)
00251     {
00252         mouseDrag(MouseButton::Left);
00253     }
00254 
00255     void DDContainer::setPropertyOverride(const std::string& _key, const std::string& _value)
00256     {
00258         if (_key == "NeedDragDrop")
00259             setNeedDragDrop(utility::parseValue<bool>(_value));
00260 
00261         else
00262         {
00263             Base::setPropertyOverride(_key, _value);
00264             return;
00265         }
00266 
00267         eventChangeProperty(this, _key, _value);
00268     }
00269 
00270     void DDContainer::setNeedDragDrop(bool _value)
00271     {
00272         mNeedDragDrop = _value;
00273     }
00274 
00275     bool DDContainer::getNeedDragDrop() const
00276     {
00277         return mNeedDragDrop;
00278     }
00279 
00280     void DDContainer::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
00281     {
00282     }
00283 
00284     void DDContainer::resetDrag()
00285     {
00286         _resetContainer(false);
00287     }
00288 
00289 } // namespace MyGUI