1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-03 02:45:33 +00:00
openmw/extern/mygui_3.0.1/MyGUIEngine/src/MyGUI_Window.cpp

463 lines
13 KiB
C++
Raw Normal View History

/*!
@file
@author Albert Semenov
@date 11/2007
@module
*/
/*
This file is part of MyGUI.
MyGUI is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
MyGUI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_Window.h"
#include "MyGUI_Macros.h"
#include "MyGUI_Gui.h"
#include "MyGUI_ControllerManager.h"
#include "MyGUI_InputManager.h"
#include "MyGUI_WidgetManager.h"
#include "MyGUI_ResourceSkin.h"
namespace MyGUI
{
const float WINDOW_ALPHA_ACTIVE = ALPHA_MAX;
const float WINDOW_ALPHA_FOCUS = 0.7f;
const float WINDOW_ALPHA_DEACTIVE = 0.3f;
const float WINDOW_SPEED_COEF = 3.0f;
const int WINDOW_SNAP_DISTANSE = 10;
Window::Window() :
mWidgetCaption(nullptr),
mMouseRootFocus(false),
mKeyRootFocus(false),
mIsAutoAlpha(false),
mSnap(false),
mAnimateSmooth(false)
{
}
void Window::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
{
Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
initialiseWidgetSkin(_info);
}
Window::~Window()
{
shutdownWidgetSkin();
}
void Window::baseChangeWidgetSkin(ResourceSkin* _info)
{
shutdownWidgetSkin();
Base::baseChangeWidgetSkin(_info);
initialiseWidgetSkin(_info);
}
void Window::initialiseWidgetSkin(ResourceSkin* _info)
{
// нам нужен фокус клавы
mNeedKeyFocus = true;
// дефолтные размеры
mMinmax.set(0, 0, 3000, 3000);
bool main_move = false;
// парсим свойства
const MapString& properties = _info->getProperties();
if (!properties.empty())
{
MapString::const_iterator iter = properties.find("Snap");
if (iter != properties.end()) mSnap = utility::parseBool(iter->second);
iter = properties.find("MainMove");
if (iter != properties.end())
{
setUserString("Scale", "1 1 0 0");
main_move = true;
}
}
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
{
if (*(*iter)->_getInternalData<std::string>() == "Client")
{
MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned");
mWidgetClient = (*iter);
if (main_move)
{
(*iter)->setUserString("Scale", "1 1 0 0");
(*iter)->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
(*iter)->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
}
}
else if (*(*iter)->_getInternalData<std::string>() == "Caption")
{
MYGUI_DEBUG_ASSERT( ! mWidgetCaption, "widget already assigned");
mWidgetCaption = (*iter);
mWidgetCaption->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
mWidgetCaption->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
}
else if (*(*iter)->_getInternalData<std::string>() == "Button")
{
(*iter)->eventMouseButtonClick = newDelegate(this, &Window::notifyPressedButtonEvent);
}
else if (*(*iter)->_getInternalData<std::string>() == "Action")
{
(*iter)->eventMouseButtonPressed = newDelegate(this, &Window::notifyMousePressed);
(*iter)->eventMouseDrag = newDelegate(this, &Window::notifyMouseDrag);
}
}
}
void Window::shutdownWidgetSkin()
{
mWidgetClient = nullptr;
mWidgetCaption = nullptr;
}
// переопределяем для присвоению клиенту
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)
{
MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
if (mWidgetClient != nullptr) return mWidgetClient->createWidgetT(_style, _type, _skin, _coord, _align, _layer, _name);
return Base::baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name);
}
void Window::onMouseChangeRootFocus(bool _focus)
{
mMouseRootFocus = _focus;
updateAlpha();
Base::onMouseChangeRootFocus(_focus);
}
void Window::onKeyChangeRootFocus(bool _focus)
{
mKeyRootFocus = _focus;
updateAlpha();
Base::onKeyChangeRootFocus(_focus);
}
void Window::onMouseDrag(int _left, int _top)
{
// на тот случай, если двигать окно, можно за любое место виджета
notifyMouseDrag(this, _left, _top);
Base::onMouseDrag(_left, _top);
}
void Window::onMouseButtonPressed(int _left, int _top, MouseButton _id)
{
notifyMousePressed(this, _left, _top, _id);
Base::onMouseButtonPressed(_left, _top, _id);
}
void Window::notifyMousePressed(MyGUI::Widget* _sender, int _left, int _top, MouseButton _id)
{
if (MouseButton::Left == _id)
{
mPreActionCoord = mCoord;
mCurrentActionScale = IntCoord::parse(_sender->getUserString("Scale"));
}
}
void Window::notifyPressedButtonEvent(MyGUI::Widget* _sender)
{
eventWindowButtonPressed(this, _sender->getUserString("Event"));
}
void Window::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top)
{
const IntPoint& point = InputManager::getInstance().getLastLeftPressed();
IntCoord coord = mCurrentActionScale;
coord.left *= (_left - point.left);
coord.top *= (_top - point.top);
coord.width *= (_left - point.left);
coord.height *= (_top - point.top);
if (coord.left == 0 && coord.top == 0)
setSize((mPreActionCoord + coord).size());
else if (coord.width == 0 && coord.height == 0)
setPosition((mPreActionCoord + coord).point());
else
setCoord(mPreActionCoord + coord);
// посылаем событие о изменении позиции и размере
eventWindowChangeCoord(this);
}
void Window::updateAlpha()
{
if (!mIsAutoAlpha) return;
float alpha;
if (mKeyRootFocus) alpha = WINDOW_ALPHA_ACTIVE;
else if (mMouseRootFocus) alpha = WINDOW_ALPHA_FOCUS;
else alpha = WINDOW_ALPHA_DEACTIVE;
ControllerFadeAlpha * controller = createControllerFadeAlpha(alpha, WINDOW_SPEED_COEF, true);
ControllerManager::getInstance().addItem(this, controller);
}
void Window::setAutoAlpha(bool _auto)
{
mIsAutoAlpha = _auto;
if (!_auto) setAlpha(ALPHA_MAX);
else
{
if (mKeyRootFocus) setAlpha(WINDOW_ALPHA_ACTIVE);
else if (mMouseRootFocus) setAlpha(WINDOW_ALPHA_FOCUS);
else setAlpha(WINDOW_ALPHA_DEACTIVE);
}
}
void Window::setPosition(const IntPoint& _point)
{
IntPoint point = _point;
// прилепляем к краям
if (mSnap)
{
IntCoord coord(point, mCoord.size());
getSnappedCoord(coord);
point = coord.point();
}
Base::setPosition(point);
}
void Window::setSize(const IntSize& _size)
{
IntSize size = _size;
// прилепляем к краям
if (size.width < mMinmax.left) size.width = mMinmax.left;
else if (size.width > mMinmax.right) size.width = mMinmax.right;
if (size.height < mMinmax.top) size.height = mMinmax.top;
else if (size.height > mMinmax.bottom) size.height = mMinmax.bottom;
if ((size.width == mCoord.width) && (size.height == mCoord.height) ) return;
if (mSnap)
{
IntCoord coord(mCoord.point(), size);
getSnappedCoord(coord);
size = coord.size();
}
Base::setSize(size);
}
void Window::setCoord(const IntCoord& _coord)
{
IntPoint pos = _coord.point();
IntSize size = _coord.size();
if (size.width < mMinmax.left)
{
int offset = mMinmax.left - size.width;
size.width = mMinmax.left;
if ((pos.left - mCoord.left) > offset) pos.left -= offset;
else pos.left = mCoord.left;
}
else if (size.width > mMinmax.right)
{
int offset = mMinmax.right - size.width;
size.width = mMinmax.right;
if ((pos.left - mCoord.left) < offset) pos.left -= offset;
else pos.left = mCoord.left;
}
if (size.height < mMinmax.top)
{
int offset = mMinmax.top - size.height;
size.height = mMinmax.top;
if ((pos.top - mCoord.top) > offset) pos.top -= offset;
else pos.top = mCoord.top;
}
else if (size.height > mMinmax.bottom)
{
int offset = mMinmax.bottom - size.height;
size.height = mMinmax.bottom;
if ((pos.top - mCoord.top) < offset) pos.top -= offset;
else pos.top = mCoord.top;
}
// прилепляем к краям
if (mSnap)
{
IntCoord coord(pos, size);
getSnappedCoord(coord);
size = coord.size();
}
IntCoord coord(pos, size);
if (coord == mCoord) return;
Base::setCoord(coord);
}
void Window::setCaption(const UString& _caption)
{
if (mWidgetCaption != nullptr) mWidgetCaption->setCaption(_caption);
else Base::setCaption(_caption);
}
const UString& Window::getCaption()
{
if (mWidgetCaption != nullptr) return mWidgetCaption->getCaption();
return Base::getCaption();
}
void Window::destroySmooth()
{
ControllerFadeAlpha * controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
controller->eventPostAction = newDelegate(action::actionWidgetDestroy);
ControllerManager::getInstance().addItem(this, controller);
}
void Window::animateStop(Widget* _widget)
{
if (mAnimateSmooth)
{
ControllerManager::getInstance().removeItem(this);
mAnimateSmooth = false;
}
}
void Window::setVisible(bool _visible)
{
if (mAnimateSmooth)
{
ControllerManager::getInstance().removeItem(this);
setAlpha(getAlphaVisible());
setEnabledSilent(true);
mAnimateSmooth = false;
}
Base::setVisible(_visible);
}
float Window::getAlphaVisible()
{
return (mIsAutoAlpha && !mKeyRootFocus) ? WINDOW_ALPHA_DEACTIVE : ALPHA_MAX;
}
void Window::getSnappedCoord(IntCoord& _coord)
{
if (abs(_coord.left) <= WINDOW_SNAP_DISTANSE) _coord.left = 0;
if (abs(_coord.top) <= WINDOW_SNAP_DISTANSE) _coord.top = 0;
IntSize view_size;
if (getCroppedParent() == nullptr)
view_size = this->getLayer()->getSize();
else
view_size = ((Widget*)getCroppedParent())->getSize();
if ( abs(_coord.left + _coord.width - view_size.width) < WINDOW_SNAP_DISTANSE) _coord.left = view_size.width - _coord.width;
if ( abs(_coord.top + _coord.height - view_size.height) < WINDOW_SNAP_DISTANSE) _coord.top = view_size.height - _coord.height;
}
void Window::setVisibleSmooth(bool _visible)
{
mAnimateSmooth = true;
ControllerManager::getInstance().removeItem(this);
if (_visible)
{
setEnabledSilent(true);
if ( ! isVisible() )
{
setAlpha(ALPHA_MIN);
Base::setVisible(true);
}
ControllerFadeAlpha * controller = createControllerFadeAlpha(getAlphaVisible(), WINDOW_SPEED_COEF, true);
controller->eventPostAction = newDelegate(this, &Window::animateStop);
ControllerManager::getInstance().addItem(this, controller);
}
else
{
setEnabledSilent(false);
ControllerFadeAlpha * controller = createControllerFadeAlpha(ALPHA_MIN, WINDOW_SPEED_COEF, false);
controller->eventPostAction = newDelegate(action::actionWidgetHide);
ControllerManager::getInstance().addItem(this, controller);
}
}
ControllerFadeAlpha* Window::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
{
ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
controller->setAlpha(_alpha);
controller->setCoef(_coef);
controller->setEnabled(_enable);
return controller;
}
void Window::setMinSize(const IntSize& _value)
{
mMinmax.left = _value.width;
mMinmax.top = _value.height;
}
IntSize Window::getMinSize()
{
return IntSize(mMinmax.left, mMinmax.top);
}
void Window::setMaxSize(const IntSize& _value)
{
mMinmax.right = _value.width;
mMinmax.bottom = _value.height;
}
IntSize Window::getMaxSize()
{
return IntSize(mMinmax.right, mMinmax.bottom);
}
void Window::setProperty(const std::string& _key, const std::string& _value)
{
if (_key == "Window_AutoAlpha") setAutoAlpha(utility::parseValue<bool>(_value));
else if (_key == "Window_Snap") setSnap(utility::parseValue<bool>(_value));
else if (_key == "Window_MinSize") setMinSize(utility::parseValue<IntSize>(_value));
else if (_key == "Window_MaxSize") setMaxSize(utility::parseValue<IntSize>(_value));
#ifndef MYGUI_DONT_USE_OBSOLETE
else if (_key == "Window_MinMax")
{
IntRect rect = IntRect::parse(_value);
setMinSize(rect.left, rect.top);
setMaxSize(rect.right, rect.bottom);
MYGUI_LOG(Warning, "Window_MinMax is obsolete, use Window_MinSize or Window_MaxSize");
}
#endif // MYGUI_DONT_USE_OBSOLETE
else
{
Base::setProperty(_key, _value);
return;
}
eventChangeProperty(this, _key, _value);
}
} // namespace MyGUI