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