MyGUI 3.0.1
MyGUI_DDContainer.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_DDContainer.h"
00025 #include "MyGUI_InputManager.h"
00026 #include "MyGUI_LayerManager.h"
00027 
00028 namespace MyGUI
00029 {
00030 
00031     DDContainer::DDContainer() :
00032         mDropResult(false),
00033         mNeedDrop(false),
00034         mStartDrop(false),
00035         mOldDrop(nullptr),
00036         mCurrentSender(nullptr),
00037         mDropSenderIndex(ITEM_NONE),
00038         mDropItem(nullptr),
00039         mNeedDragDrop(false),
00040         mReseiverContainer(nullptr)
00041     {
00042     }
00043 
00044     void DDContainer::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
00045     {
00046         Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
00047 
00048         initialiseWidgetSkin(_info);
00049     }
00050 
00051     DDContainer::~DDContainer()
00052     {
00053         shutdownWidgetSkin();
00054     }
00055 
00056     void DDContainer::baseChangeWidgetSkin(ResourceSkin* _info)
00057     {
00058         shutdownWidgetSkin();
00059         Base::baseChangeWidgetSkin(_info);
00060         initialiseWidgetSkin(_info);
00061     }
00062 
00063     void DDContainer::initialiseWidgetSkin(ResourceSkin* _info)
00064     {
00065     }
00066 
00067     void DDContainer::shutdownWidgetSkin()
00068     {
00069     }
00070 
00071     void DDContainer::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00072     {
00073         // смещение внутри виджета, куда кликнули мышкой
00074         mClickInWidget = InputManager::getInstance().getLastLeftPressed() - getAbsolutePosition();
00075 
00076         mouseButtonPressed(_id);
00077 
00078         Base::onMouseButtonPressed(_left, _top, _id);
00079     }
00080 
00081     void DDContainer::onMouseButtonReleased(int _left, int _top, MouseButton _id)
00082     {
00083         mouseButtonReleased(_id);
00084 
00085         Base::onMouseButtonReleased(_left, _top, _id);
00086     }
00087 
00088     void DDContainer::onMouseDrag(int _left, int _top)
00089     {
00090         mouseDrag();
00091 
00092         Base::onMouseDrag(_left, _top);
00093     }
00094 
00095     void DDContainer::mouseButtonPressed(MouseButton _id)
00096     {
00097         if (MouseButton::Left == _id)
00098         {
00099             // сбрасываем инфу для дропа
00100             mDropResult = false;
00101             mOldDrop = nullptr;
00102             mDropInfo.reset();
00103             mReseiverContainer = nullptr;
00104 
00105             // сбрасываем, чтобы обновился дропный виджет
00106             mCurrentSender = nullptr;
00107             mStartDrop = false;
00108 
00109         }
00110         // если нажата другая клавиша и был дроп то сбрасываем
00111         else
00112         {
00113             endDrop(true);
00114         }
00115     }
00116 
00117     void DDContainer::mouseButtonReleased(MouseButton _id)
00118     {
00119         if (MouseButton::Left == _id)
00120         {
00121             endDrop(false);
00122         }
00123     }
00124 
00125     void DDContainer::mouseDrag()
00126     {
00127         // нужно ли обновить данные
00128         bool update = false;
00129 
00130         // первый раз дропаем елемент
00131         if (!mStartDrop && mDropSenderIndex != ITEM_NONE)
00132         {
00133             mStartDrop = true;
00134             mNeedDrop = false;
00135             update = true;
00136             // запрос на нужность дропа по индексу
00137             mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00138             mReseiverContainer = nullptr;
00139 
00140             eventStartDrag(this, mDropInfo, mNeedDrop);
00141 
00142             if (mNeedDrop)
00143             {
00144                 eventChangeDDState(this, DDItemState::Start);
00145                 setEnableToolTip(false);
00146             }
00147             else
00148             {
00149                 // сбрасываем фокус мыши (не обязательно)
00150                 InputManager::getInstance().resetMouseCaptureWidget();
00151             }
00152         }
00153 
00154         // дроп не нужен
00155         if (!mNeedDrop)
00156         {
00157             return;
00158         }
00159 
00160         // делаем запрос, над кем наша мыша
00161         const IntPoint& point = InputManager::getInstance().getMousePosition();
00162         Widget* item = LayerManager::getInstance().getWidgetFromPoint(point.left, point.top);
00163 
00164         updateDropItems();
00165 
00166         // если равно, значит уже спрашивали
00167         if (mOldDrop == item) return;
00168         mOldDrop = item;
00169 
00170         // сбрасываем старую подсветку
00171         if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
00172 
00173         mDropResult = false;
00174         mReseiverContainer = nullptr;
00175         Widget* receiver = nullptr;
00176         size_t receiver_index = ITEM_NONE;
00177         // есть виджет под нами
00178         if (item)
00179         {
00180             // делаем запрос на индекс по произвольному виджету
00181             item->_getContainer(receiver, receiver_index);
00182             // работаем только с контейнерами
00183             if (receiver && receiver->isType<DDContainer>())
00184             {
00185                 // подписываемся на информацию о валидности дропа
00186                 mReseiverContainer = static_cast<DDContainer*>(receiver);
00187                 mReseiverContainer->_eventInvalideContainer = newDelegate(this, &DDContainer::notifyInvalideDrop);
00188 
00189                 // делаем запрос на возможность дропа
00190                 mDropInfo.set(this, mDropSenderIndex, mReseiverContainer, receiver_index);
00191 
00192                 eventRequestDrop(this, mDropInfo, mDropResult);
00193 
00194                 // устанавливаем новую подсветку
00195                 mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, true, mDropResult);
00196             }
00197             else
00198             {
00199                 mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00200             }
00201         }
00202         // нет виджета под нами
00203         else
00204         {
00205             mDropInfo.set(this, mDropSenderIndex, nullptr, ITEM_NONE);
00206         }
00207 
00208         DDItemState state;
00209 
00210         DDWidgetState data(mDropSenderIndex);
00211         data.update = update;
00212 
00213         if (receiver == nullptr)
00214         {
00215             data.accept = false;
00216             data.refuse = false;
00217             state = DDItemState::Miss;
00218         }
00219         else if (mDropResult)
00220         {
00221             data.accept = true;
00222             data.refuse = false;
00223             state = DDItemState::Accept;
00224         }
00225         else
00226         {
00227             data.accept = false;
00228             data.refuse = true;
00229             state = DDItemState::Refuse;
00230         }
00231 
00232         updateDropItemsState(data);
00233 
00234         eventChangeDDState(this, state);
00235     }
00236 
00237     void DDContainer::endDrop(bool _reset)
00238     {
00239         if (mStartDrop)
00240         {
00241             removeDropItems();
00242 
00243             // сбрасываем старую подсветку
00244             if (mReseiverContainer) mReseiverContainer->_setContainerItemInfo(mDropInfo.receiver_index, false, false);
00245 
00246             if (_reset) mDropResult = false;
00247             eventDropResult(this, mDropInfo, mDropResult);
00248             eventChangeDDState(this, DDItemState::End);
00249             setEnableToolTip(true);
00250 
00251             // сбрасываем инфу для дропа
00252             mStartDrop = false;
00253             mDropResult = false;
00254             mNeedDrop = false;
00255             mOldDrop = nullptr;
00256             mDropInfo.reset();
00257             mReseiverContainer = nullptr;
00258             mDropSenderIndex = ITEM_NONE;
00259         }
00260     }
00261 
00262     void DDContainer::removeDropItems()
00263     {
00264         mDropItem = nullptr;
00265     }
00266 
00267     void DDContainer::updateDropItems()
00268     {
00269 
00270         if (mDropItem == nullptr)
00271         {
00272             requestDragWidgetInfo(this, mDropItem, mDropDimension);
00273         }
00274 
00275         const IntPoint& point = InputManager::getInstance().getMousePositionByLayer();
00276 
00277         if (mDropItem)
00278         {
00279             mDropItem->setCoord(point.left - mClickInWidget.left + mDropDimension.left, point.top - mClickInWidget.top + mDropDimension.top, mDropDimension.width, mDropDimension.height);
00280             mDropItem->setVisible(true);
00281         }
00282     }
00283 
00284     void DDContainer::updateDropItemsState(const DDWidgetState& _state)
00285     {
00286         eventUpdateDropState(this, mDropItem, _state);
00287     }
00288 
00289     void DDContainer::notifyInvalideDrop(DDContainer* _sender)
00290     {
00291         mouseDrag();
00292     }
00293 
00294     void DDContainer::_getContainer(Widget*& _container, size_t& _index)
00295     {
00296         _container = this;
00297         _index = ITEM_NONE;
00298     }
00299 
00300     void DDContainer::setProperty(const std::string& _key, const std::string& _value)
00301     {
00302         if (_key == "DDContainer_NeedDragDrop") setNeedDragDrop(utility::parseValue<bool>(_value));
00303         else
00304         {
00305             Base::setProperty(_key, _value);
00306             return;
00307         }
00308         eventChangeProperty(this, _key, _value);
00309     }
00310 
00311 } // namespace MyGUI