/*!
@file
@author Albert Semenov
@date 01/2008
@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 .
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_Message.h"
#include "MyGUI_ResourceSkin.h"
#include "MyGUI_WidgetManager.h"
#include "MyGUI_LayerManager.h"
#include "MyGUI_InputManager.h"
#include "MyGUI_ResourceManager.h"
#include "MyGUI_Gui.h"
#include "MyGUI_ControllerManager.h"
#include "MyGUI_StaticImage.h"
#include "MyGUI_LanguageManager.h"
namespace MyGUI
{
const float MESSAGE_ALPHA_MAX = 0.5f;
const float MESSAGE_ALPHA_MIN = 0.0f;
const float MESSAGE_SPEED_COEF = 3.0f;
Message::Message() :
mWidgetText(nullptr),
mInfoOk(MessageBoxStyle::None),
mInfoCancel(MessageBoxStyle::None),
mSmoothShow(false),
mWidgetFade(nullptr),
mIcon(nullptr),
mLeftOffset1(0),
mLeftOffset2(0)
{
}
void Message::_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);
}
Message::~Message()
{
shutdownWidgetSkin();
}
void Message::baseChangeWidgetSkin(ResourceSkin* _info)
{
shutdownWidgetSkin();
Base::baseChangeWidgetSkin(_info);
initialiseWidgetSkin(_info);
}
void Message::initialiseWidgetSkin(ResourceSkin* _info)
{
// парсим виджет для текста
for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
{
if (*(*iter)->_getInternalData() == "Text")
{
MYGUI_DEBUG_ASSERT( ! mWidgetText, "widget already assigned");
mWidgetText = (*iter);
mOffsetText.set(mCoord.width - mWidgetText->getWidth(), mCoord.height - mWidgetText->getHeight());
mLeftOffset2 = mLeftOffset1 = mWidgetText->getLeft();
}
else if (*(*iter)->_getInternalData() == "Icon")
{
MYGUI_DEBUG_ASSERT( ! mIcon, "widget already assigned");
mIcon = (*iter)->castType();
}
}
//MYGUI_ASSERT(nullptr != mWidgetText, "Child Text not found in skin (MessageBox must have widget for text)");
if (mIcon != nullptr)
{
mLeftOffset2 = mIcon->getRight() + 3;
}
// парсим свойства
const MapString& properties = _info->getProperties();
if (!properties.empty())
{
MapString::const_iterator iter = properties.find("ButtonSkin");
if (iter != properties.end()) mButtonSkin = iter->second;
iter = properties.find("ButtonType");
if (iter != properties.end()) mButtonType = iter->second;
iter = properties.find("ButtonSize");
if (iter != properties.end()) mButtonSize = IntSize::parse(iter->second);
iter = properties.find("ButtonOffset");
if (iter != properties.end()) mButtonOffset = IntSize::parse(iter->second);
iter = properties.find("DefaultLayer");
if (iter != properties.end()) mDefaultLayer = iter->second;
iter = properties.find("FadeSkin");
if (iter != properties.end()) mFadeSkin = iter->second;
iter = properties.find("FadeLayer");
if (iter != properties.end()) mFadeLayer = iter->second;
}
}
void Message::shutdownWidgetSkin()
{
mWidgetText = nullptr;
mIcon = nullptr;
}
void Message::setMessageText(const UString& _message)
{
if (mWidgetText != nullptr)
mWidgetText->setCaption(_message);
updateSize();
}
MessageBoxStyle Message::addButtonName(const UString& _name)
{
//FIXME
if (mVectorButton.size() >= MessageBoxStyle::_CountUserButtons)
{
MYGUI_LOG(Warning, "Too many buttons in message box, ignored");
return MessageBoxStyle::None;
}
// бит, номер кнопки + смещение до Button1
MessageBoxStyle info = MessageBoxStyle(MessageBoxStyle::Enum(MYGUI_FLAG(mVectorButton.size() + MessageBoxStyle::_IndexUserButton1)));
// запоминаем кнопки для отмены и подтверждения
if (mVectorButton.empty()) mInfoOk = info;
mInfoCancel = info;
Widget* button = createWidgetT(mButtonType, mButtonSkin, IntCoord(), Align::Left | Align::Bottom);
button->eventMouseButtonClick = newDelegate(this, &Message::notifyButtonClick);
button->setCaption(_name);
button->_setInternalData(info);
mVectorButton.push_back(button);
updateSize();
return info;
}
void Message::setMessageIcon(MessageBoxStyle _icon)
{
if (nullptr == mIcon) return;
if (mIcon->getItemResource() != nullptr)
{
mIcon->setItemName( getIconName(_icon.getIconIndex()) );
}
else
{
mIcon->setImageIndex(_icon.getIconIndex());
}
updateSize();
}
void Message::setMessageButton(MessageBoxStyle _info)
{
clearButton();
std::vector buttons = _info.getButtons();
for (size_t index=0; index_setInternalData(info);
// первая кнопка
if (mVectorButton.size() == 1) mInfoOk = info;
// последняя кнопка
mInfoCancel = info;
}
updateSize();
}
void Message::setMessageStyle(MessageBoxStyle _style)
{
setMessageButton(_style);
setMessageIcon(_style);
}
void Message::notifyButtonClick(MyGUI::Widget* _sender)
{
_destroyMessage(*_sender->_getInternalData());
}
void Message::clearButton()
{
for (VectorWidgetPtr::iterator iter=mVectorButton.begin(); iter!=mVectorButton.end(); ++iter)
{
WidgetManager::getInstance().destroyWidget(*iter);
}
mVectorButton.clear();
}
void Message::onKeyButtonPressed(KeyCode _key, Char _char)
{
Base::onKeyButtonPressed(_key, _char);
if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter)) _destroyMessage(mInfoOk);
else if (_key == KeyCode::Escape) _destroyMessage(mInfoCancel);
}
void Message::_destroyMessage(MessageBoxStyle _result)
{
eventMessageBoxResult(this, _result);
if (nullptr != mWidgetFade)
{
if (mSmoothShow)
{
ControllerFadeAlpha* controller = createControllerFadeAlpha(MESSAGE_ALPHA_MIN, MESSAGE_SPEED_COEF, false);
controller->eventPostAction = newDelegate(action::actionWidgetDestroy);
ControllerManager::getInstance().addItem(mWidgetFade, controller);
}
else
{
WidgetManager::getInstance().destroyWidget(mWidgetFade);
}
}
if (mSmoothShow) destroySmooth();
else WidgetManager::getInstance().destroyWidget(this);
}
void Message::setSmoothShow(bool _smooth)
{
mSmoothShow = _smooth;
if (mSmoothShow)
{
setAlpha(ALPHA_MIN);
setVisible(true);
setVisibleSmooth(true);
}
}
void Message::setWindowFade(bool _fade)
{
return; //пока пропустим
if (_fade)
{
if (nullptr == mWidgetFade)
{
Gui& gui = Gui::getInstance();
mWidgetFade = gui.createWidgetT(Widget::getClassTypeName(), mFadeSkin, IntCoord(0, 0, gui.getViewSize().width, gui.getViewSize().height), Align::Stretch, mFadeLayer);
if (mSmoothShow)
{
mWidgetFade->setVisible(false);
ControllerFadeAlpha* controller = createControllerFadeAlpha(MESSAGE_ALPHA_MAX, MESSAGE_SPEED_COEF, false);
ControllerManager::getInstance().addItem(mWidgetFade, controller);
}
else
{
mWidgetFade->setAlpha(MESSAGE_ALPHA_MAX);
}
}
}
else
{
if (nullptr != mWidgetFade)
{
WidgetManager::getInstance().destroyWidget(mWidgetFade);
mWidgetFade = nullptr;
}
}
}
const char * Message::getIconName(size_t _index)
{
static const size_t CountIcons = 4;
static const char * IconNames[CountIcons + 1] = { "Info", "Quest", "Error", "Warning", "" };
if (_index >= CountIcons) return IconNames[CountIcons];
return IconNames[_index];
}
MyGUI::Message* Message::createMessageBox(
const std::string& _skin,
const UString& _caption,
const UString& _message,
MessageBoxStyle _style,
const std::string& _layer,
bool _modal,
const std::string& _button1,
const std::string& _button2,
const std::string& _button3,
const std::string& _button4)
{
Message* mess = Gui::getInstance().createWidget(_skin, IntCoord(), Align::Default, _layer);
mess->setCaption(_caption);
mess->setMessageText(_message);
mess->setSmoothShow(true);
if (_modal) mess->setWindowFade(true);
mess->setMessageStyle(_style);
if (!_button1.empty())
{
mess->addButtonName(_button1);
if (!_button2.empty())
{
mess->addButtonName(_button2);
if (!_button3.empty())
{
mess->addButtonName(_button3);
}
}
}
if (_layer.empty()) LayerManager::getInstance().attachToLayerNode(mess->getDefaultLayer(), mess);
if (_modal) InputManager::getInstance().addWidgetModal(mess);
return mess;
}
void Message::updateSize()
{
ISubWidgetText* text = nullptr;
if (mWidgetText != nullptr)
text = mWidgetText->getSubWidgetText();
IntSize size = text == nullptr ? IntSize() : text->getTextSize();
// минимум высота иконки
if ((nullptr != mIcon) && (mIcon->getImageIndex() != ITEM_NONE))
{
if (size.height < mIcon->getHeight()) size.height = mIcon->getHeight();
size.width += mIcon->getSize().width;
}
size += mOffsetText;
size.width += 3;
int width = ((int)mVectorButton.size() * mButtonSize.width) + (((int)mVectorButton.size()+1) * mButtonOffset.width);
if (size.width < width) size.width = width;
int offset = (size.width - width)/2;
offset += mButtonOffset.width;
const IntSize& view = Gui::getInstance().getViewSize();
setCoord((view.width-size.width)/2, (view.height-size.height)/2, size.width, size.height);
if (nullptr != mIcon)
{
if (mWidgetText != nullptr)
{
if (mIcon->getImageIndex() != ITEM_NONE) mWidgetText->setCoord(mLeftOffset2, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight());
else mWidgetText->setCoord(mLeftOffset1, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight());
}
}
for (VectorWidgetPtr::iterator iter=mVectorButton.begin(); iter!=mVectorButton.end(); ++iter)
{
(*iter)->setCoord(offset, mCoord.height - mButtonOffset.height, mButtonSize.width, mButtonSize.height);
offset += mButtonOffset.width + mButtonSize.width;
}
}
ControllerFadeAlpha* Message::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
{
ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
ControllerFadeAlpha* controller = item->castType();
controller->setAlpha(_alpha);
controller->setCoef(_coef);
controller->setEnabled(_enable);
return controller;
}
void Message::setMessageModal(bool _value)
{
if (_value) InputManager::getInstance().addWidgetModal(this);
else InputManager::getInstance().removeWidgetModal(this);
}
UString Message::getButtonName(MessageBoxStyle _style)
{
size_t index = _style.getButtonIndex();
const char* tag = getButtonTag(index);
UString result = LanguageManager::getInstance().replaceTags(utility::toString("#{", tag, "}"));
if (result == tag) return getButtonName(index);
return result;
}
const char * Message::getButtonName(size_t _index)
{
static const size_t Count = 9;
static const char * Names[Count + 1] = { "Ok", "Yes", "No", "Abort", "Retry", "Ignore", "Cancel", "Try", "Continue", "" };
if (_index >= Count) return Names[Count];
return Names[_index];
}
const char * Message::getButtonTag(size_t _index)
{
static const size_t Count = 9;
static const char * Names[Count + 1] = { "MyGUI_MessageBox_Ok", "MyGUI_MessageBox_Yes", "MyGUI_MessageBox_No", "MyGUI_MessageBox_Abort", "MyGUI_MessageBox_Retry", "MyGUI_MessageBox_Ignore", "MyGUI_MessageBox_Cancel", "MyGUI_MessageBox_Try", "MyGUI_MessageBox_Continue", "" };
if (_index >= Count) return Names[Count];
return Names[_index];
}
void Message::endMessage(MessageBoxStyle _result)
{
_destroyMessage(_result);
}
void Message::endMessage()
{
_destroyMessage(mInfoCancel);
}
void Message::setProperty(const std::string& _key, const std::string& _value)
{
if (_key == "Message_Caption") setCaption(_value);
else if (_key == "Message_Message") setMessageText(_value);
else if (_key == "Message_Modal") setMessageModal(utility::parseValue(_value));
else if (_key == "Message_Button") setMessageButton(utility::parseValue(_value));
else if (_key == "Message_AddButton") addButtonName(_value);
else if (_key == "Message_SmoothShow") setSmoothShow(utility::parseValue(_value));
else if (_key == "Message_Fade") setWindowFade(utility::parseValue(_value));
else
{
Base::setProperty(_key, _value);
return;
}
eventChangeProperty(this, _key, _value);
}
} // namespace MyGUI