MyGUI  3.0.1
MyGUI_Window.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_Window.h"
00025 #include "MyGUI_Macros.h"
00026 #include "MyGUI_Gui.h"
00027 #include "MyGUI_ControllerManager.h"
00028 #include "MyGUI_InputManager.h"
00029 #include "MyGUI_WidgetManager.h"
00030 #include "MyGUI_ResourceSkin.h"
00031 
00032 namespace MyGUI
00033 {
00034 
00035     const float WINDOW_ALPHA_ACTIVE = ALPHA_MAX;
00036     const float WINDOW_ALPHA_FOCUS = 0.7f;
00037     const float WINDOW_ALPHA_DEACTIVE = 0.3f;
00038     const float WINDOW_SPEED_COEF = 3.0f;
00039 
00040     const int WINDOW_SNAP_DISTANSE = 10;
00041 
00042     Window::Window() :
00043         mWidgetCaption(nullptr),
00044         mMouseRootFocus(false),
00045         mKeyRootFocus(false),
00046         mIsAutoAlpha(false),
00047         mSnap(false),
00048         mAnimateSmooth(false)
00049     {
00050     }
00051 
00052     void Window::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
00053     {
00054         Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
00055 
00056         initialiseWidgetSkin(_info);
00057     }
00058 
00059     Window::~Window()
00060     {
00061         shutdownWidgetSkin();
00062     }
00063 
00064     void Window::baseChangeWidgetSkin(ResourceSkin* _info)
00065     {
00066         shutdownWidgetSkin();
00067         Base::baseChangeWidgetSkin(_info);
00068         initialiseWidgetSkin(_info);
00069     }
00070 
00071     void Window::initialiseWidgetSkin(ResourceSkin* _info)
00072     {
00073         // нам нужен фокус клавы
00074         mNeedKeyFocus = true;
00075 
00076         // дефолтные размеры
00077         mMinmax.set(0, 0, 3000, 3000);
00078 
00079         bool main_move = false;
00080         // парсим свойства
00081         const MapString& properties = _info->getProperties();
00082         if (!properties.empty())
00083         {
00084             MapString::const_iterator iter = properties.find("Snap");
00085             if (iter != properties.end()) mSnap = utility::parseBool(iter->second);
00086             iter = properties.find("MainMove");
00087             if (iter != properties.end())
00088             {
00089                 setUserString("Scale", "1 1 0 0");
00090                 main_move = true;
00091             }
00092         }
00093 
00094         for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
00095         {
00096             if (*(*iter)->_getInternalData<std::string>() == "Client")
00097             {
00098                 MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned");
00099                 mWidgetClient = (*iter);
00100                 if (main_move)
00101                 {
00102                     (*iter)->setUserString("Scale", "1 1 0 0");
00103                     (*iter)->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
00104                     (*iter)->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
00105                 }
00106             }
00107             else if (*(*iter)->_getInternalData<std::string>() == "Caption")
00108             {
00109                 MYGUI_DEBUG_ASSERT( ! mWidgetCaption, "widget already assigned");
00110                 mWidgetCaption = (*iter);
00111                 mWidgetCaption->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
00112                 mWidgetCaption->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
00113             }
00114             else if (*(*iter)->_getInternalData<std::string>() == "Button")
00115             {
00116                 (*iter)->eventMouseButtonClick = newDelegate(this, &Window::notifyPressedButtonEvent);
00117             }
00118             else if (*(*iter)->_getInternalData<std::string>() == "Action")
00119             {
00120                 (*iter)->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
00121                 (*iter)->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
00122             }
00123         }
00124 
00125     }
00126 
00127     void Window::shutdownWidgetSkin()
00128     {
00129         mWidgetClient = nullptr;
00130         mWidgetCaption = nullptr;
00131     }
00132 
00133     // переопределяем для присвоению клиенту
00134     Widget* Window::baseCreateWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name)
00135     {
00136         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00137         if (mWidgetClient != nullptr) return mWidgetClient->createWidgetT(_style, _type, _skin, _coord, _align, _layer, _name);
00138         return Base::baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name);
00139     }
00140 
00141     void Window::onMouseChangeRootFocus(bool _focus)
00142     {
00143         mMouseRootFocus = _focus;
00144         updateAlpha();
00145 
00146         Base::onMouseChangeRootFocus(_focus);
00147     }
00148 
00149     void Window::onKeyChangeRootFocus(bool _focus)
00150     {
00151         mKeyRootFocus = _focus;
00152         updateAlpha();
00153 
00154         Base::onKeyChangeRootFocus(_focus);
00155     }
00156 
00157     void Window::onMouseDrag(int _left, int _top)
00158     {
00159         // на тот случай, если двигать окно, можно за любое место виджета
00160         notifyMouseDrag(this, _left, _top);
00161 
00162         Base::onMouseDrag(_left, _top);
00163     }
00164 
00165     void Window::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00166     {
00167         notifyMousePressed(this, _left, _top, _id);
00168 
00169         Base::onMouseButtonPressed(_left, _top, _id);
00170     }
00171 
00172     void Window::notifyMousePressed(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00173     {
00174         if (MouseButton::Left == _id)
00175         {
00176             mPreActionCoord = mCoord;
00177             mCurrentActionScale = IntCoord::parse(_sender->getUserString("Scale"));
00178         }
00179     }
00180 
00181     void Window::notifyPressedButtonEvent(MyGUI::Widget* _sender)
00182     {
00183         eventWindowButtonPressed(this, _sender->getUserString("Event"));
00184     }
00185 
00186     void Window::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top)
00187     {
00188         const IntPoint& point = InputManager::getInstance().getLastLeftPressed();
00189 
00190         IntCoord coord = mCurrentActionScale;
00191         coord.left *= (_left - point.left);
00192         coord.top *= (_top - point.top);
00193         coord.width *= (_left - point.left);
00194         coord.height *= (_top - point.top);
00195 
00196         if (coord.left == 0 && coord.top == 0)
00197             setSize((mPreActionCoord + coord).size());
00198         else if (coord.width == 0 && coord.height == 0)
00199             setPosition((mPreActionCoord + coord).point());
00200         else
00201             setCoord(mPreActionCoord + coord);
00202 
00203         // посылаем событие о изменении позиции и размере
00204         eventWindowChangeCoord(this);
00205     }
00206 
00207     void Window::updateAlpha()
00208     {
00209         if (!mIsAutoAlpha) return;
00210 
00211         float alpha;
00212         if (mKeyRootFocus) alpha = WINDOW_ALPHA_ACTIVE;
00213         else if (mMouseRootFocus) alpha = WINDOW_ALPHA_FOCUS;
00214         else alpha = WINDOW_ALPHA_DEACTIVE;
00215 
00216         ControllerFadeAlpha * controller = createControllerFadeAlpha(alpha, WINDOW_SPEED_COEF, true);
00217         ControllerManager::getInstance().addItem(this, controller);
00218     }
00219 
00220     void Window::setAutoAlpha(bool _auto)
00221     {
00222         mIsAutoAlpha = _auto;
00223         if (!_auto) setAlpha(ALPHA_MAX);
00224         else
00225         {
00226             if (mKeyRootFocus) setAlpha(WINDOW_ALPHA_ACTIVE);
00227             else if (mMouseRootFocus) setAlpha(WINDOW_ALPHA_FOCUS);
00228             else setAlpha(WINDOW_ALPHA_DEACTIVE);
00229         }
00230     }
00231 
00232     void Window::setPosition(const IntPoint& _point)
00233     {
00234         IntPoint point = _point;
00235         // прилепляем к краям
00236         if (mSnap)
00237         {
00238             IntCoord coord(point, mCoord.size());
00239             getSnappedCoord(coord);
00240             point = coord.point();
00241         }
00242 
00243         Base::setPosition(point);
00244     }
00245 
00246     void Window::setSize(const IntSize& _size)
00247     {
00248         IntSize size = _size;
00249         // прилепляем к краям
00250 
00251         if (size.width < mMinmax.left) size.width = mMinmax.left;
00252         else if (size.width > mMinmax.right) size.width = mMinmax.right;
00253         if (size.height < mMinmax.top) size.height = mMinmax.top;
00254         else if (size.height > mMinmax.bottom) size.height = mMinmax.bottom;
00255         if ((size.width == mCoord.width) && (size.height == mCoord.height) ) return;
00256 
00257         if (mSnap)
00258         {
00259             IntCoord coord(mCoord.point(), size);
00260             getSnappedCoord(coord);
00261             size = coord.size();
00262         }
00263 
00264         Base::setSize(size);
00265     }
00266 
00267     void Window::setCoord(const IntCoord& _coord)
00268     {
00269         IntPoint pos = _coord.point();
00270         IntSize size = _coord.size();
00271 
00272         if (size.width < mMinmax.left)
00273         {
00274             int offset = mMinmax.left - size.width;
00275             size.width = mMinmax.left;
00276             if ((pos.left - mCoord.left) > offset) pos.left -= offset;
00277             else pos.left = mCoord.left;
00278         }
00279         else if (size.width > mMinmax.right)
00280         {
00281             int offset = mMinmax.right - size.width;
00282             size.width = mMinmax.right;
00283             if ((pos.left - mCoord.left) < offset) pos.left -= offset;
00284             else pos.left = mCoord.left;
00285         }
00286         if (size.height < mMinmax.top)
00287         {
00288             int offset = mMinmax.top - size.height;
00289             size.height = mMinmax.top;
00290             if ((pos.top - mCoord.top) > offset) pos.top -= offset;
00291             else pos.top = mCoord.top;
00292         }
00293         else if (size.height > mMinmax.bottom)
00294         {
00295             int offset = mMinmax.bottom - size.height;
00296             size.height = mMinmax.bottom;
00297             if ((pos.top - mCoord.top) < offset) pos.top -= offset;
00298             else pos.top = mCoord.top;
00299         }
00300 
00301         // прилепляем к краям
00302         if (mSnap)
00303         {
00304             IntCoord coord(pos, size);
00305             getSnappedCoord(coord);
00306             size = coord.size();
00307         }
00308 
00309         IntCoord coord(pos, size);
00310         if (coord == mCoord) return;
00311 
00312         Base::setCoord(coord);
00313     }
00314 
00315     void Window::setCaption(const UString& _caption)
00316     {
00317         if (mWidgetCaption != nullptr) mWidgetCaption->setCaption(_caption);
00318         else Base::setCaption(_caption);
00319     }
00320 
00321     const UString& Window::getCaption()
00322     {
00323         if (mWidgetCaption != nullptr) return mWidgetCaption->getCaption();
00324         return Base::getCaption();
00325     }
00326 
00327     void Window::destroySmooth()
00328     {
00329         ControllerFadeAlpha * controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00330         controller->eventPostAction = newDelegate(action::actionWidgetDestroy);
00331         ControllerManager::getInstance().addItem(this, controller);
00332     }
00333 
00334     void Window::animateStop(Widget* _widget)
00335     {
00336         if (mAnimateSmooth)
00337         {
00338             ControllerManager::getInstance().removeItem(this);
00339             mAnimateSmooth = false;
00340         }
00341     }
00342 
00343     void Window::setVisible(bool _visible)
00344     {
00345 
00346         if (mAnimateSmooth)
00347         {
00348             ControllerManager::getInstance().removeItem(this);
00349             setAlpha(getAlphaVisible());
00350             setEnabledSilent(true);
00351             mAnimateSmooth = false;
00352         }
00353 
00354         Base::setVisible(_visible);
00355     }
00356 
00357     float Window::getAlphaVisible()
00358     {
00359         return (mIsAutoAlpha && !mKeyRootFocus) ? WINDOW_ALPHA_DEACTIVE : ALPHA_MAX;
00360     }
00361 
00362     void Window::getSnappedCoord(IntCoord& _coord)
00363     {
00364         if (abs(_coord.left) <= WINDOW_SNAP_DISTANSE) _coord.left = 0;
00365         if (abs(_coord.top) <= WINDOW_SNAP_DISTANSE) _coord.top = 0;
00366 
00367         IntSize view_size;
00368         if (getCroppedParent() == nullptr)
00369             view_size = this->getLayer()->getSize();
00370         else
00371             view_size = ((Widget*)getCroppedParent())->getSize();
00372 
00373         if ( abs(_coord.left + _coord.width - view_size.width) < WINDOW_SNAP_DISTANSE) _coord.left = view_size.width - _coord.width;
00374         if ( abs(_coord.top + _coord.height - view_size.height) < WINDOW_SNAP_DISTANSE) _coord.top = view_size.height - _coord.height;
00375     }
00376 
00377     void Window::setVisibleSmooth(bool _visible)
00378     {
00379         mAnimateSmooth = true;
00380         ControllerManager::getInstance().removeItem(this);
00381 
00382         if (_visible)
00383         {
00384             setEnabledSilent(true);
00385             if ( ! isVisible() )
00386             {
00387                 setAlpha(ALPHA_MIN);
00388                 Base::setVisible(true);
00389             }
00390             ControllerFadeAlpha * controller = createControllerFadeAlpha(getAlphaVisible(), WINDOW_SPEED_COEF, true);
00391             controller->eventPostAction = newDelegate(this, &Window::animateStop);
00392             ControllerManager::getInstance().addItem(this, controller);
00393         }
00394         else
00395         {
00396             setEnabledSilent(false);
00397             ControllerFadeAlpha * controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00398             controller->eventPostAction = newDelegate(action::actionWidgetHide);
00399             ControllerManager::getInstance().addItem(this, controller);
00400         }
00401     }
00402 
00403     ControllerFadeAlpha* Window::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
00404     {
00405         ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
00406         ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
00407 
00408         controller->setAlpha(_alpha);
00409         controller->setCoef(_coef);
00410         controller->setEnabled(_enable);
00411 
00412         return controller;
00413     }
00414 
00415     void Window::setMinSize(const IntSize& _value)
00416     {
00417         mMinmax.left = _value.width;
00418         mMinmax.top = _value.height;
00419     }
00420 
00421     IntSize Window::getMinSize()
00422     {
00423         return IntSize(mMinmax.left, mMinmax.top);
00424     }
00425 
00426     void Window::setMaxSize(const IntSize& _value)
00427     {
00428         mMinmax.right = _value.width;
00429         mMinmax.bottom = _value.height;
00430     }
00431 
00432     IntSize Window::getMaxSize()
00433     {
00434         return IntSize(mMinmax.right, mMinmax.bottom);
00435     }
00436 
00437     void Window::setProperty(const std::string& _key, const std::string& _value)
00438     {
00439         if (_key == "Window_AutoAlpha") setAutoAlpha(utility::parseValue<bool>(_value));
00440         else if (_key == "Window_Snap") setSnap(utility::parseValue<bool>(_value));
00441         else if (_key == "Window_MinSize") setMinSize(utility::parseValue<IntSize>(_value));
00442         else if (_key == "Window_MaxSize") setMaxSize(utility::parseValue<IntSize>(_value));
00443 
00444 #ifndef MYGUI_DONT_USE_OBSOLETE
00445         else if (_key == "Window_MinMax")
00446         {
00447             IntRect rect = IntRect::parse(_value);
00448             setMinSize(rect.left, rect.top);
00449             setMaxSize(rect.right, rect.bottom);
00450             MYGUI_LOG(Warning, "Window_MinMax is obsolete, use Window_MinSize or Window_MaxSize");
00451         }
00452 #endif // MYGUI_DONT_USE_OBSOLETE
00453 
00454         else
00455         {
00456             Base::setProperty(_key, _value);
00457             return;
00458         }
00459         eventChangeProperty(this, _key, _value);
00460     }
00461 
00462 } // namespace MyGUI