MyGUI  3.2.0
MyGUI_Window.cpp
Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of MyGUI.
00008 
00009     MyGUI is free software: you can redistribute it and/or modify
00010     it under the terms of the GNU Lesser General Public License as published by
00011     the Free Software Foundation, either version 3 of the License, or
00012     (at your option) any later version.
00013 
00014     MyGUI is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00021 */
00022 #include "MyGUI_Precompiled.h"
00023 #include "MyGUI_Window.h"
00024 #include "MyGUI_Macros.h"
00025 #include "MyGUI_Gui.h"
00026 #include "MyGUI_ControllerManager.h"
00027 #include "MyGUI_InputManager.h"
00028 #include "MyGUI_WidgetManager.h"
00029 #include "MyGUI_ResourceSkin.h"
00030 
00031 namespace MyGUI
00032 {
00033     const float WINDOW_ALPHA_ACTIVE = ALPHA_MAX;
00034     const float WINDOW_ALPHA_FOCUS = 0.7f;
00035     const float WINDOW_ALPHA_DEACTIVE = 0.3f;
00036     const float WINDOW_SPEED_COEF = 3.0f;
00037 
00038     const int WINDOW_SNAP_DISTANSE = 10;
00039 
00040     Window::Window() :
00041         mWidgetCaption(nullptr),
00042         mMouseRootFocus(false),
00043         mKeyRootFocus(false),
00044         mIsAutoAlpha(false),
00045         mSnap(false),
00046         mAnimateSmooth(false),
00047         mClient(nullptr),
00048         mMovable(true)
00049     {
00050     }
00051 
00052     void Window::initialiseOverride()
00053     {
00054         Base::initialiseOverride();
00055 
00056         // FIXME нам нужен фокус клавы
00057         setNeedKeyFocus(true);
00058 
00059         // дефолтные размеры
00060         mMinmax.set(
00061             (std::numeric_limits<int>::min)(),
00062             (std::numeric_limits<int>::min)(),
00063             (std::numeric_limits<int>::max)(),
00064             (std::numeric_limits<int>::max)());
00065 
00066         bool main_move = false;
00067         if (isUserString("MainMove"))
00068         {
00069             setUserString("Scale", "1 1 0 0");
00070             main_move = true;
00071         }
00072 
00073         assignWidget(mClient, "Client");
00074         if (mClient != nullptr)
00075         {
00076             if (main_move)
00077             {
00078                 mClient->setUserString("Scale", "1 1 0 0");
00079                 mClient->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00080                 mClient->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00081                 mClient->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00082             }
00083             setWidgetClient(mClient);
00084         }
00085 
00086         assignWidget(mWidgetCaption, "Caption");
00087         if (mWidgetCaption != nullptr)
00088         {
00089             mWidgetCaption->setUserString("Scale", "1 1 0 0");
00090             mWidgetCaption->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00091             mWidgetCaption->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00092             mWidgetCaption->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00093         }
00094 
00095         VectorWidgetPtr buttons = getSkinWidgetsByName("Button");
00096         for (VectorWidgetPtr::iterator iter = buttons.begin(); iter != buttons.end(); ++iter)
00097         {
00098             (*iter)->eventMouseButtonClick += newDelegate(this, &Window::notifyPressedButtonEvent);
00099         }
00100 
00101         VectorWidgetPtr actions = getSkinWidgetsByName("Action");
00102         for (VectorWidgetPtr::iterator iter = actions.begin(); iter != actions.end(); ++iter)
00103         {
00104             (*iter)->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00105             (*iter)->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00106             (*iter)->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00107         }
00108 
00109         const size_t countNames = 8;
00110         const char* resizers[2][countNames] =
00111         {
00112             {"ResizeLeftTop", "ResizeTop", "ResizeRightTop", "ResizeRight", "ResizeRightBottom", "ResizeBottom", "ResizeLeftBottom", "ResizeLeft"},
00113             {"Left Top", "Top", "Right Top", "Right", "Right Bottom", "Bottom", "Left Bottom", "Left"}
00114         };
00115 
00116         for (size_t index = 0; index < countNames; ++ index)
00117         {
00118             Widget* widget = nullptr;
00119             assignWidget(widget, resizers[0][index]);
00120             if (widget != nullptr)
00121             {
00122                 widget->eventMouseButtonPressed += newDelegate(this, &Window::notifyMousePressed);
00123                 widget->eventMouseButtonReleased += newDelegate(this, &Window::notifyMouseReleased);
00124                 widget->eventMouseDrag += newDelegate(this, &Window::notifyMouseDrag);
00125                 widget->setUserString("Action", resizers[1][index]);
00126             }
00127         }
00128     }
00129 
00130     void Window::shutdownOverride()
00131     {
00132         mClient = nullptr;
00133         mWidgetCaption = nullptr;
00134 
00135         Base::shutdownOverride();
00136     }
00137 
00138     void Window::onMouseChangeRootFocus(bool _focus)
00139     {
00140         mMouseRootFocus = _focus;
00141         updateAlpha();
00142 
00143         Base::onMouseChangeRootFocus(_focus);
00144     }
00145 
00146     void Window::onKeyChangeRootFocus(bool _focus)
00147     {
00148         mKeyRootFocus = _focus;
00149         updateAlpha();
00150 
00151         Base::onKeyChangeRootFocus(_focus);
00152     }
00153 
00154     void Window::onMouseDrag(int _left, int _top, MouseButton _id)
00155     {
00156         // на тот случай, если двигать окно, можно за любое место виджета
00157         notifyMouseDrag(this, _left, _top, _id);
00158 
00159         Base::onMouseDrag(_left, _top, _id);
00160     }
00161 
00162     void Window::onMouseButtonPressed(int _left, int _top, MouseButton _id)
00163     {
00164         notifyMousePressed(this, _left, _top, _id);
00165 
00166         Base::onMouseButtonPressed(_left, _top, _id);
00167     }
00168 
00169     void Window::onMouseButtonReleased(int _left, int _top, MouseButton _id)
00170     {
00171         notifyMouseReleased(this, _left, _top, _id);
00172 
00173         Base::onMouseButtonReleased(_left, _top, _id);
00174     }
00175 
00176     void Window::notifyMousePressed(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00177     {
00178         if (MouseButton::Left == _id)
00179         {
00180             mPreActionCoord = mCoord;
00181             mCurrentActionScale = _getActionScale(_sender);
00182         }
00183     }
00184 
00185     void Window::notifyPressedButtonEvent(MyGUI::Widget* _sender)
00186     {
00187         eventWindowButtonPressed(this, _sender->getUserString("Event"));
00188     }
00189 
00190     void Window::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
00191     {
00192         if (_id != MouseButton::Left)
00193             return;
00194 
00195         const IntPoint& point = InputManager::getInstance().getLastPressedPosition(MouseButton::Left);
00196 
00197         IntCoord coord = mCurrentActionScale;
00198         coord.left *= (_left - point.left);
00199         coord.top *= (_top - point.top);
00200         coord.width *= (_left - point.left);
00201         coord.height *= (_top - point.top);
00202 
00203         if (coord.empty())
00204             return;
00205 
00206         if (coord.left == 0 && coord.top == 0)
00207             setSize((mPreActionCoord + coord).size());
00208         else if (coord.width == 0 && coord.height == 0)
00209             setPosition((mPreActionCoord + coord).point());
00210         else
00211             setCoord(mPreActionCoord + coord);
00212 
00213         // посылаем событие о изменении позиции и размере
00214         eventWindowChangeCoord(this);
00215     }
00216 
00217     void Window::updateAlpha()
00218     {
00219         if (!mIsAutoAlpha)
00220             return;
00221 
00222         float alpha;
00223         if (mKeyRootFocus)
00224             alpha = WINDOW_ALPHA_ACTIVE;
00225         else if (mMouseRootFocus)
00226             alpha = WINDOW_ALPHA_FOCUS;
00227         else
00228             alpha = WINDOW_ALPHA_DEACTIVE;
00229 
00230         ControllerFadeAlpha* controller = createControllerFadeAlpha(alpha, WINDOW_SPEED_COEF, true);
00231         ControllerManager::getInstance().addItem(this, controller);
00232     }
00233 
00234     void Window::setAutoAlpha(bool _auto)
00235     {
00236         mIsAutoAlpha = _auto;
00237         if (!_auto)
00238             setAlpha(ALPHA_MAX);
00239         else
00240         {
00241             if (mKeyRootFocus)
00242                 setAlpha(WINDOW_ALPHA_ACTIVE);
00243             else if (mMouseRootFocus)
00244                 setAlpha(WINDOW_ALPHA_FOCUS);
00245             else
00246                 setAlpha(WINDOW_ALPHA_DEACTIVE);
00247         }
00248     }
00249 
00250     void Window::setPosition(const IntPoint& _point)
00251     {
00252         IntPoint point = _point;
00253         // прилепляем к краям
00254         if (mSnap)
00255         {
00256             IntCoord coord(point, mCoord.size());
00257             getSnappedCoord(coord);
00258             point = coord.point();
00259         }
00260 
00261         Base::setPosition(point);
00262     }
00263 
00264     void Window::setSize(const IntSize& _size)
00265     {
00266         IntSize size = _size;
00267         // прилепляем к краям
00268 
00269         if (size.width < mMinmax.left)
00270             size.width = mMinmax.left;
00271         else if (size.width > mMinmax.right)
00272             size.width = mMinmax.right;
00273         if (size.height < mMinmax.top)
00274             size.height = mMinmax.top;
00275         else if (size.height > mMinmax.bottom)
00276             size.height = mMinmax.bottom;
00277         if ((size.width == mCoord.width) && (size.height == mCoord.height))
00278             return;
00279 
00280         if (mSnap)
00281         {
00282             IntCoord coord(mCoord.point(), size);
00283             getSnappedCoord(coord);
00284             size = coord.size();
00285         }
00286 
00287         Base::setSize(size);
00288     }
00289 
00290     void Window::setCoord(const IntCoord& _coord)
00291     {
00292         IntPoint pos = _coord.point();
00293         IntSize size = _coord.size();
00294 
00295         if (size.width < mMinmax.left)
00296         {
00297             int offset = mMinmax.left - size.width;
00298             size.width = mMinmax.left;
00299             if ((pos.left - mCoord.left) > offset)
00300                 pos.left -= offset;
00301             else
00302                 pos.left = mCoord.left;
00303         }
00304         else if (size.width > mMinmax.right)
00305         {
00306             int offset = mMinmax.right - size.width;
00307             size.width = mMinmax.right;
00308             if ((pos.left - mCoord.left) < offset)
00309                 pos.left -= offset;
00310             else
00311                 pos.left = mCoord.left;
00312         }
00313         if (size.height < mMinmax.top)
00314         {
00315             int offset = mMinmax.top - size.height;
00316             size.height = mMinmax.top;
00317             if ((pos.top - mCoord.top) > offset)
00318                 pos.top -= offset;
00319             else
00320                 pos.top = mCoord.top;
00321         }
00322         else if (size.height > mMinmax.bottom)
00323         {
00324             int offset = mMinmax.bottom - size.height;
00325             size.height = mMinmax.bottom;
00326             if ((pos.top - mCoord.top) < offset)
00327                 pos.top -= offset;
00328             else
00329                 pos.top = mCoord.top;
00330         }
00331 
00332         // прилепляем к краям
00333         if (mSnap)
00334         {
00335             IntCoord coord(pos, size);
00336             getSnappedCoord(coord);
00337             size = coord.size();
00338         }
00339 
00340         IntCoord coord(pos, size);
00341         if (coord == mCoord)
00342             return;
00343 
00344         Base::setCoord(coord);
00345     }
00346 
00347     void Window::setCaption(const UString& _caption)
00348     {
00349         if (mWidgetCaption != nullptr)
00350             mWidgetCaption->setCaption(_caption);
00351         else
00352             Base::setCaption(_caption);
00353     }
00354 
00355     const UString& Window::getCaption()
00356     {
00357         if (mWidgetCaption != nullptr)
00358             return mWidgetCaption->getCaption();
00359         return Base::getCaption();
00360     }
00361 
00362     void Window::destroySmooth()
00363     {
00364         ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00365         controller->eventPostAction += newDelegate(action::actionWidgetDestroy);
00366         ControllerManager::getInstance().addItem(this, controller);
00367     }
00368 
00369     void Window::animateStop(Widget* _widget)
00370     {
00371         if (mAnimateSmooth)
00372         {
00373             ControllerManager::getInstance().removeItem(this);
00374             mAnimateSmooth = false;
00375         }
00376     }
00377 
00378     void Window::setVisible(bool _visible)
00379     {
00380         if (mAnimateSmooth)
00381         {
00382             ControllerManager::getInstance().removeItem(this);
00383             setAlpha(getAlphaVisible());
00384             setEnabledSilent(true);
00385             mAnimateSmooth = false;
00386         }
00387 
00388         Base::setVisible(_visible);
00389     }
00390 
00391     float Window::getAlphaVisible() const
00392     {
00393         return (mIsAutoAlpha && !mKeyRootFocus) ? WINDOW_ALPHA_DEACTIVE : ALPHA_MAX;
00394     }
00395 
00396     void Window::getSnappedCoord(IntCoord& _coord)
00397     {
00398         if (abs(_coord.left) <= WINDOW_SNAP_DISTANSE) _coord.left = 0;
00399         if (abs(_coord.top) <= WINDOW_SNAP_DISTANSE) _coord.top = 0;
00400 
00401         const IntSize view_size = getParentSize();
00402 
00403         if ( abs(_coord.left + _coord.width - view_size.width) < WINDOW_SNAP_DISTANSE)
00404             _coord.left = view_size.width - _coord.width;
00405         if ( abs(_coord.top + _coord.height - view_size.height) < WINDOW_SNAP_DISTANSE)
00406             _coord.top = view_size.height - _coord.height;
00407     }
00408 
00409     void Window::setVisibleSmooth(bool _visible)
00410     {
00411         mAnimateSmooth = true;
00412         ControllerManager::getInstance().removeItem(this);
00413 
00414         if (_visible)
00415         {
00416             setEnabledSilent(true);
00417             if (!getVisible())
00418             {
00419                 setAlpha(ALPHA_MIN);
00420                 Base::setVisible(true);
00421             }
00422             ControllerFadeAlpha* controller = createControllerFadeAlpha(getAlphaVisible(), WINDOW_SPEED_COEF, true);
00423             controller->eventPostAction += newDelegate(this, &Window::animateStop);
00424             ControllerManager::getInstance().addItem(this, controller);
00425         }
00426         else
00427         {
00428             setEnabledSilent(false);
00429             ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
00430             controller->eventPostAction += newDelegate(action::actionWidgetHide);
00431             ControllerManager::getInstance().addItem(this, controller);
00432         }
00433     }
00434 
00435     ControllerFadeAlpha* Window::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
00436     {
00437         ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
00438         ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
00439 
00440         controller->setAlpha(_alpha);
00441         controller->setCoef(_coef);
00442         controller->setEnabled(_enable);
00443 
00444         return controller;
00445     }
00446 
00447     void Window::setMinSize(const IntSize& _value)
00448     {
00449         mMinmax.left = _value.width;
00450         mMinmax.top = _value.height;
00451     }
00452 
00453     IntSize Window::getMinSize()
00454     {
00455         return IntSize(mMinmax.left, mMinmax.top);
00456     }
00457 
00458     void Window::setMaxSize(const IntSize& _value)
00459     {
00460         mMinmax.right = _value.width;
00461         mMinmax.bottom = _value.height;
00462     }
00463 
00464     IntSize Window::getMaxSize()
00465     {
00466         return IntSize(mMinmax.right, mMinmax.bottom);
00467     }
00468 
00469     void Window::setPropertyOverride(const std::string& _key, const std::string& _value)
00470     {
00471         if (_key == "AutoAlpha")
00472             setAutoAlpha(utility::parseValue<bool>(_value));
00473         else if (_key == "Snap")
00474             setSnap(utility::parseValue<bool>(_value));
00475         else if (_key == "MinSize")
00476             setMinSize(utility::parseValue<IntSize>(_value));
00477         else if (_key == "MaxSize")
00478             setMaxSize(utility::parseValue<IntSize>(_value));
00479         else if (_key == "Movable")
00480             setMovable(utility::parseValue<bool>(_value));
00481         else
00482         {
00483             Base::setPropertyOverride(_key, _value);
00484             return;
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 } // namespace MyGUI