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

462 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
@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