MyGUI
3.2.0
|
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