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