MyGUI  3.2.1
MyGUI_Window.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_Window.h"
00009 #include "MyGUI_Macros.h"
00010 #include "MyGUI_Gui.h"
00011 #include "MyGUI_ControllerManager.h"
00012 #include "MyGUI_InputManager.h"
00013 #include "MyGUI_WidgetManager.h"
00014 #include "MyGUI_ResourceSkin.h"
00015 
00016 namespace MyGUI
00017 {
00018     const float WINDOW_ALPHA_ACTIVE = ALPHA_MAX;
00019     const float WINDOW_ALPHA_FOCUS = 0.7f;
00020     const float WINDOW_ALPHA_DEACTIVE = 0.3f;
00021     const float WINDOW_SPEED_COEF = 3.0f;
00022 
00023     const int WINDOW_SNAP_DISTANSE = 10;
00024 
00025     Window::Window() :
00026         mWidgetCaption(nullptr),
00027         mMouseRootFocus(false),
00028         mKeyRootFocus(false),
00029         mIsAutoAlpha(false),
00030         mSnap(false),
00031         mAnimateSmooth(false),
00032         mClient(nullptr),
00033         mMovable(true)
00034     {
00035     }
00036 
00037     void Window::initialiseOverride()
00038     {
00039         Base::initialiseOverride();
00040 
00041         // FIXME нам нужен фокус клавы
00042         setNeedKeyFocus(true);
00043 
00044         // дефолтные размеры
00045         mMinmax.set(
00046             (std::numeric_limits<int>::min)(),
00047             (std::numeric_limits<int>::min)(),
00048             (std::numeric_limits<int>::max)(),
00049             (std::numeric_limits<int>::max)());
00050 
00051         bool main_move = false;
00052         if (isUserString("MainMove"))
00053         {
00054             setUserString("Scale", "1 1 0 0");
00055             main_move = true;
00056         }
00057 
00059         assignWidget(mClient, "Client");
00060         if (mClient != nullptr)
00061         {
00062             if (main_move)
00063             {
00064                 mClient->setUserString("Scale", "1 1 0 0");
00065                 mClient->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00066                 mClient->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00067                 mClient->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00068             }
00069             setWidgetClient(mClient);
00070         }
00071 
00073         assignWidget(mWidgetCaption, "Caption");
00074         if (mWidgetCaption != nullptr)
00075         {
00076             mWidgetCaption->setUserString("Scale", "1 1 0 0");
00077             mWidgetCaption->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00078             mWidgetCaption->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00079             mWidgetCaption->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00080         }
00081 
00082         VectorWidgetPtr buttons = getSkinWidgetsByName("Button");
00083         for (VectorWidgetPtr::iterator iter = buttons.begin(); iter != buttons.end(); ++iter)
00084         {
00085             (*iter)->eventMouseButtonClick += newDelegate(this, &Window::notifyPressedButtonEvent);
00086         }
00087 
00088         VectorWidgetPtr actions = getSkinWidgetsByName("Action");
00089         for (VectorWidgetPtr::iterator iter = actions.begin(); iter != actions.end(); ++iter)
00090         {
00091             (*iter)->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00092             (*iter)->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00093             (*iter)->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00094             (*iter)->eventMouseWheel += newDelegate(this, &Window::notifyMouseWheel);
00095         }
00096 
00097         const size_t countNames = 8;
00098         const char* resizers[2][countNames] =
00099         {
00100             {"ResizeLeftTop", "ResizeTop", "ResizeRightTop", "ResizeRight", "ResizeRightBottom", "ResizeBottom", "ResizeLeftBottom", "ResizeLeft"},
00101             {"Left Top", "Top", "Right Top", "Right", "Right Bottom", "Bottom", "Left Bottom", "Left"}
00102         };
00103 
00104         for (size_t index = 0; index < countNames; ++ index)
00105         {
00106             Widget* widget = nullptr;
00107             assignWidget(widget, resizers[0][index]);
00108             if (widget != nullptr)
00109             {
00110                 widget->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00111                 widget->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00112                 widget->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00113                 widget->eventMouseWheel += newDelegate(this, &Window::notifyMouseWheel);
00114                 widget->setUserString("Action", resizers[1][index]);
00115             }
00116         }
00117     }
00118 
00119     void Window::shutdownOverride()
00120     {
00121         mClient = nullptr;
00122         mWidgetCaption = nullptr;
00123 
00124         Base::shutdownOverride();
00125     }
00126 
00127     void Window::onMouseChangeRootFocus(bool _focus)
00128     {
00129         mMouseRootFocus = _focus;
00130         updateAlpha();
00131 
00132         Base::onMouseChangeRootFocus(_focus);
00133     }
00134 
00135     void Window::onKeyChangeRootFocus(bool _focus)
00136     {
00137         mKeyRootFocus = _focus;
00138         updateAlpha();
00139 
00140         Base::onKeyChangeRootFocus(_focus);
00141     }
00142 
00143     void Window::onMouseDrag(int _left, int _top, MouseButton _id)
00144     {
00145         // на тот случай, если двигать окно, можно за любое место виджета
00146         notifyMouseDrag(this, _left, _top, _id);
00147 
00148         Base::onMouseDrag(_left, _top, _id);
00149     }
00150 
00151     void Window::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00152     {
00153         notifyMousePressed(this, _left, _top, _id);
00154 
00155         Base::onMouseButtonPressed(_left, _top, _id);
00156     }
00157 
00158     void Window::onMouseButtonReleased(int _left, int _top, MouseButton _id)
00159     {
00160         notifyMouseReleased(this, _left, _top, _id);
00161 
00162         Base::onMouseButtonReleased(_left, _top, _id);
00163     }
00164 
00165     void Window::notifyMousePressed(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00166     {
00167         if (MouseButton::Left == _id)
00168         {
00169             mPreActionCoord = mCoord;
00170             mCurrentActionScale = _getActionScale(_sender);
00171         }
00172     }
00173 
00174     void Window::notifyPressedButtonEvent(MyGUI::Widget* _sender)
00175     {
00176         eventWindowButtonPressed(this, _sender->getUserString("Event"));
00177     }
00178 
00179     void Window::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00180     {
00181         if (_id != MouseButton::Left)
00182             return;
00183 
00184         const IntPoint& point = InputManager::getInstance().getLastPressedPosition(MouseButton::Left);
00185 
00186         IntCoord coord = mCurrentActionScale;
00187         coord.left *= (_left - point.left);
00188         coord.top *= (_top - point.top);
00189         coord.width *= (_left - point.left);
00190         coord.height *= (_top - point.top);
00191 
00192         if (coord.empty())
00193             return;
00194 
00195         if (coord.left == 0 && coord.top == 0)
00196             setSize((mPreActionCoord + coord).size());
00197         else if (coord.width == 0 && coord.height == 0)
00198             setPosition((mPreActionCoord + coord).point());
00199         else
00200             setCoord(mPreActionCoord + coord);
00201 
00202         // посылаем событие о изменении позиции и размере
00203         eventWindowChangeCoord(this);
00204     }
00205 
00206     void Window::updateAlpha()
00207     {
00208         if (!mIsAutoAlpha)
00209             return;
00210 
00211         float alpha;
00212         if (mKeyRootFocus)
00213             alpha = WINDOW_ALPHA_ACTIVE;
00214         else if (mMouseRootFocus)
00215             alpha = WINDOW_ALPHA_FOCUS;
00216         else
00217             alpha = WINDOW_ALPHA_DEACTIVE;
00218 
00219         ControllerFadeAlpha* controller = createControllerFadeAlpha(alpha, WINDOW_SPEED_COEF, true);
00220         ControllerManager::getInstance().addItem(this, controller);
00221     }
00222 
00223     void Window::setAutoAlpha(bool _auto)
00224     {
00225         mIsAutoAlpha = _auto;
00226         if (!_auto)
00227             setAlpha(ALPHA_MAX);
00228         else
00229         {
00230             if (mKeyRootFocus)
00231                 setAlpha(WINDOW_ALPHA_ACTIVE);
00232             else if (mMouseRootFocus)
00233                 setAlpha(WINDOW_ALPHA_FOCUS);
00234             else
00235                 setAlpha(WINDOW_ALPHA_DEACTIVE);
00236         }
00237     }
00238 
00239     void Window::setPosition(const IntPoint& _point)
00240     {
00241         IntPoint point = _point;
00242         // прилепляем к краям
00243         if (mSnap)
00244         {
00245             IntCoord coord(point, mCoord.size());
00246             getSnappedCoord(coord);
00247             point = coord.point();
00248         }
00249 
00250         Base::setPosition(point);
00251     }
00252 
00253     void Window::setSize(const IntSize& _size)
00254     {
00255         IntSize size = _size;
00256         // прилепляем к краям
00257 
00258         if (size.width < mMinmax.left)
00259             size.width = mMinmax.left;
00260         else if (size.width > mMinmax.right)
00261             size.width = mMinmax.right;
00262         if (size.height < mMinmax.top)
00263             size.height = mMinmax.top;
00264         else if (size.height > mMinmax.bottom)
00265             size.height = mMinmax.bottom;
00266         if ((size.width == mCoord.width) && (size.height == mCoord.height))
00267             return;
00268 
00269         if (mSnap)
00270         {
00271             IntCoord coord(mCoord.point(), size);
00272             getSnappedCoord(coord);
00273             size = coord.size();
00274         }
00275 
00276         Base::setSize(size);
00277     }
00278 
00279     void Window::setCoord(const IntCoord& _coord)
00280     {
00281         IntPoint pos = _coord.point();
00282         IntSize size = _coord.size();
00283 
00284         if (size.width < mMinmax.left)
00285         {
00286             int offset = mMinmax.left - size.width;
00287             size.width = mMinmax.left;
00288             if ((pos.left - mCoord.left) > offset)
00289                 pos.left -= offset;
00290             else
00291                 pos.left = mCoord.left;
00292         }
00293         else if (size.width > mMinmax.right)
00294         {
00295             int offset = mMinmax.right - size.width;
00296             size.width = mMinmax.right;
00297             if ((pos.left - mCoord.left) < offset)
00298                 pos.left -= offset;
00299             else
00300                 pos.left = mCoord.left;
00301         }
00302         if (size.height < mMinmax.top)
00303         {
00304             int offset = mMinmax.top - size.height;
00305             size.height = mMinmax.top;
00306             if ((pos.top - mCoord.top) > offset)
00307                 pos.top -= offset;
00308             else
00309                 pos.top = mCoord.top;
00310         }
00311         else if (size.height > mMinmax.bottom)
00312         {
00313             int offset = mMinmax.bottom - size.height;
00314             size.height = mMinmax.bottom;
00315             if ((pos.top - mCoord.top) < offset)
00316                 pos.top -= offset;
00317             else
00318                 pos.top = mCoord.top;
00319         }
00320 
00321         // прилепляем к краям
00322         if (mSnap)
00323         {
00324             IntCoord coord(pos, size);
00325             getSnappedCoord(coord);
00326             size = coord.size();
00327         }
00328 
00329         IntCoord coord(pos, size);
00330         if (coord == mCoord)
00331             return;
00332 
00333         Base::setCoord(coord);
00334     }
00335 
00336     void Window::setCaption(const UString& _caption)
00337     {
00338         if (mWidgetCaption != nullptr)
00339             mWidgetCaption->setCaption(_caption);
00340         else
00341             Base::setCaption(_caption);
00342     }
00343 
00344     const UString& Window::getCaption()
00345     {
00346         if (mWidgetCaption != nullptr)
00347             return mWidgetCaption->getCaption();
00348         return Base::getCaption();
00349     }
00350 
00351     void Window::destroySmooth()
00352     {
00353         ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00354         controller->eventPostAction += newDelegate(action::actionWidgetDestroy);
00355         ControllerManager::getInstance().addItem(this, controller);
00356     }
00357 
00358     void Window::animateStop(Widget* _widget, ControllerItem* _controller)
00359     {
00360         if (mAnimateSmooth)
00361         {
00362             ControllerManager::getInstance().removeItem(this);
00363             mAnimateSmooth = false;
00364         }
00365     }
00366 
00367     void Window::setVisible(bool _visible)
00368     {
00369         if (mAnimateSmooth)
00370         {
00371             ControllerManager::getInstance().removeItem(this);
00372             setAlpha(getAlphaVisible());
00373             setEnabledSilent(true);
00374             mAnimateSmooth = false;
00375         }
00376 
00377         Base::setVisible(_visible);
00378     }
00379 
00380     float Window::getAlphaVisible() const
00381     {
00382         return (mIsAutoAlpha && !mKeyRootFocus) ? WINDOW_ALPHA_DEACTIVE : ALPHA_MAX;
00383     }
00384 
00385     void Window::getSnappedCoord(IntCoord& _coord)
00386     {
00387         if (abs(_coord.left) <= WINDOW_SNAP_DISTANSE) _coord.left = 0;
00388         if (abs(_coord.top) <= WINDOW_SNAP_DISTANSE) _coord.top = 0;
00389 
00390         const IntSize view_size = getParentSize();
00391 
00392         if ( abs(_coord.left + _coord.width - view_size.width) < WINDOW_SNAP_DISTANSE)
00393             _coord.left = view_size.width - _coord.width;
00394         if ( abs(_coord.top + _coord.height - view_size.height) < WINDOW_SNAP_DISTANSE)
00395             _coord.top = view_size.height - _coord.height;
00396     }
00397 
00398     void Window::setVisibleSmooth(bool _visible)
00399     {
00400         mAnimateSmooth = true;
00401         ControllerManager::getInstance().removeItem(this);
00402 
00403         if (_visible)
00404         {
00405             setEnabledSilent(true);
00406             if (!getVisible())
00407             {
00408                 setAlpha(ALPHA_MIN);
00409                 Base::setVisible(true);
00410             }
00411             ControllerFadeAlpha* controller = createControllerFadeAlpha(getAlphaVisible(), WINDOW_SPEED_COEF, true);
00412             controller->eventPostAction += newDelegate(this, &Window::animateStop);
00413             ControllerManager::getInstance().addItem(this, controller);
00414         }
00415         else
00416         {
00417             setEnabledSilent(false);
00418             ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00419             controller->eventPostAction += newDelegate(action::actionWidgetHide);
00420             ControllerManager::getInstance().addItem(this, controller);
00421         }
00422     }
00423 
00424     ControllerFadeAlpha* Window::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
00425     {
00426         ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
00427         ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
00428 
00429         controller->setAlpha(_alpha);
00430         controller->setCoef(_coef);
00431         controller->setEnabled(_enable);
00432 
00433         return controller;
00434     }
00435 
00436     void Window::setMinSize(const IntSize& _value)
00437     {
00438         mMinmax.left = _value.width;
00439         mMinmax.top = _value.height;
00440     }
00441 
00442     IntSize Window::getMinSize()
00443     {
00444         return IntSize(mMinmax.left, mMinmax.top);
00445     }
00446 
00447     void Window::setMaxSize(const IntSize& _value)
00448     {
00449         mMinmax.right = _value.width;
00450         mMinmax.bottom = _value.height;
00451     }
00452 
00453     IntSize Window::getMaxSize()
00454     {
00455         return IntSize(mMinmax.right, mMinmax.bottom);
00456     }
00457 
00458     void Window::setPropertyOverride(const std::string& _key, const std::string& _value)
00459     {
00461         if (_key == "AutoAlpha")
00462             setAutoAlpha(utility::parseValue<bool>(_value));
00463 
00465         else if (_key == "Snap")
00466             setSnap(utility::parseValue<bool>(_value));
00467 
00469         else if (_key == "MinSize")
00470             setMinSize(utility::parseValue<IntSize>(_value));
00471 
00473         else if (_key == "MaxSize")
00474             setMaxSize(utility::parseValue<IntSize>(_value));
00475 
00477         else if (_key == "Movable")
00478             setMovable(utility::parseValue<bool>(_value));
00479 
00480         else
00481         {
00482             Base::setPropertyOverride(_key, _value);
00483             return;
00484         }
00485 
00486         eventChangeProperty(this, _key, _value);
00487     }
00488 
00489     const IntCoord& Window::getActionScale() const
00490     {
00491         return mCurrentActionScale;
00492     }
00493 
00494     bool Window::getAutoAlpha() const
00495     {
00496         return mIsAutoAlpha;
00497     }
00498 
00499     TextBox* Window::getCaptionWidget()
00500     {
00501         return mWidgetCaption;
00502     }
00503 
00504     void Window::setMinSize(int _width, int _height)
00505     {
00506         setMinSize(IntSize(_width, _height));
00507     }
00508 
00509     void Window::setMaxSize(int _width, int _height)
00510     {
00511         setMaxSize(IntSize(_width, _height));
00512     }
00513 
00514     void Window::setPosition(int _left, int _top)
00515     {
00516         setPosition(IntPoint(_left, _top));
00517     }
00518 
00519     void Window::setSize(int _width, int _height)
00520     {
00521         setSize(IntSize(_width, _height));
00522     }
00523 
00524     void Window::setCoord(int _left, int _top, int _width, int _height)
00525     {
00526         setCoord(IntCoord(_left, _top, _width, _height));
00527     }
00528 
00529     bool Window::getSnap() const
00530     {
00531         return mSnap;
00532     }
00533 
00534     void Window::setSnap(bool _value)
00535     {
00536         mSnap = _value;
00537     }
00538 
00539     void Window::notifyMouseReleased(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00540     {
00541         if (MouseButton::Left == _id)
00542         {
00543             mCurrentActionScale.clear();
00544         }
00545     }
00546 
00547     IntCoord Window::_getActionScale(Widget* _widget)
00548     {
00549         if (_widget->isUserString("Scale"))
00550         {
00551             IntCoord result = IntCoord::parse(_widget->getUserString("Scale"));
00552 
00553             if (result == IntCoord(1, 1, 0, 0) && !mMovable)
00554                 result.clear();
00555 
00556             return result;
00557         }
00558         else if (_widget->isUserString("Action"))
00559         {
00560             const std::string& action = _widget->getUserString("Action");
00561             if (action == "Move")
00562             {
00563                 if (mMovable)
00564                     return IntCoord(1, 1, 0, 0);
00565                 else
00566                     return IntCoord();
00567             }
00568 
00569             IntCoord coord;
00570             Align align = Align::parse(action);
00571 
00572             if (align.isLeft())
00573             {
00574                 coord.left = 1;
00575                 coord.width = -1;
00576             }
00577             else if (align.isRight())
00578             {
00579                 coord.width = 1;
00580             }
00581 
00582             if (align.isTop())
00583             {
00584                 coord.top = 1;
00585                 coord.height = -1;
00586             }
00587             else if (align.isBottom())
00588             {
00589                 coord.height = 1;
00590             }
00591 
00592             return coord;
00593         }
00594 
00595         return IntCoord();
00596     }
00597 
00598     void Window::setMovable(bool _value)
00599     {
00600         mMovable = _value;
00601     }
00602 
00603     bool Window::getMovable() const
00604     {
00605         return mMovable;
00606     }
00607 
00608     void Window::notifyMouseWheel(MyGUI::Widget* _sender, int _rel)
00609     {
00610         onMouseWheel(_rel);
00611         eventMouseWheel(_sender, _rel);
00612     }
00613 
00614 } // namespace MyGUI