MyGUI  3.0.1
MyGUI_Message.cpp
Go to the documentation of this file.
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_Message.h"
00025 #include "MyGUI_ResourceSkin.h"
00026 #include "MyGUI_WidgetManager.h"
00027 #include "MyGUI_LayerManager.h"
00028 #include "MyGUI_InputManager.h"
00029 #include "MyGUI_ResourceManager.h"
00030 #include "MyGUI_Gui.h"
00031 #include "MyGUI_ControllerManager.h"
00032 #include "MyGUI_StaticImage.h"
00033 #include "MyGUI_LanguageManager.h"
00034 
00035 namespace MyGUI
00036 {
00037 
00038     const float MESSAGE_ALPHA_MAX = 0.5f;
00039     const float MESSAGE_ALPHA_MIN = 0.0f;
00040     const float MESSAGE_SPEED_COEF = 3.0f;
00041 
00042     Message::Message() :
00043         mWidgetText(nullptr),
00044         mInfoOk(MessageBoxStyle::None),
00045         mInfoCancel(MessageBoxStyle::None),
00046         mSmoothShow(false),
00047         mWidgetFade(nullptr),
00048         mIcon(nullptr),
00049         mLeftOffset1(0),
00050         mLeftOffset2(0)
00051     {
00052     }
00053 
00054     void Message::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
00055     {
00056         Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
00057 
00058         initialiseWidgetSkin(_info);
00059     }
00060 
00061     Message::~Message()
00062     {
00063         shutdownWidgetSkin();
00064     }
00065 
00066     void Message::baseChangeWidgetSkin(ResourceSkin* _info)
00067     {
00068         shutdownWidgetSkin();
00069         Base::baseChangeWidgetSkin(_info);
00070         initialiseWidgetSkin(_info);
00071     }
00072 
00073     void Message::initialiseWidgetSkin(ResourceSkin* _info)
00074     {
00075         // парсим виджет для текста
00076         for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
00077         {
00078             if (*(*iter)->_getInternalData<std::string>() == "Text")
00079             {
00080                 MYGUI_DEBUG_ASSERT( ! mWidgetText, "widget already assigned");
00081                 mWidgetText = (*iter);
00082                 mOffsetText.set(mCoord.width - mWidgetText->getWidth(), mCoord.height - mWidgetText->getHeight());
00083                 mLeftOffset2 = mLeftOffset1 = mWidgetText->getLeft();
00084             }
00085             else if (*(*iter)->_getInternalData<std::string>() == "Icon")
00086             {
00087                 MYGUI_DEBUG_ASSERT( ! mIcon, "widget already assigned");
00088                 mIcon = (*iter)->castType<StaticImage>();
00089             }
00090         }
00091         //MYGUI_ASSERT(nullptr != mWidgetText, "Child Text not found in skin (MessageBox must have widget for text)");
00092 
00093         if (mIcon != nullptr)
00094         {
00095             mLeftOffset2 = mIcon->getRight() + 3;
00096         }
00097 
00098         // парсим свойства
00099         const MapString& properties = _info->getProperties();
00100         if (!properties.empty())
00101         {
00102             MapString::const_iterator iter = properties.find("ButtonSkin");
00103             if (iter != properties.end()) mButtonSkin = iter->second;
00104             iter = properties.find("ButtonType");
00105             if (iter != properties.end()) mButtonType = iter->second;
00106             iter = properties.find("ButtonSize");
00107             if (iter != properties.end()) mButtonSize = IntSize::parse(iter->second);
00108             iter = properties.find("ButtonOffset");
00109             if (iter != properties.end()) mButtonOffset = IntSize::parse(iter->second);
00110             iter = properties.find("DefaultLayer");
00111             if (iter != properties.end()) mDefaultLayer = iter->second;
00112             iter = properties.find("FadeSkin");
00113             if (iter != properties.end()) mFadeSkin = iter->second;
00114             iter = properties.find("FadeLayer");
00115             if (iter != properties.end()) mFadeLayer = iter->second;
00116         }
00117 
00118     }
00119 
00120     void Message::shutdownWidgetSkin()
00121     {
00122         mWidgetText = nullptr;
00123         mIcon = nullptr;
00124     }
00125 
00126     void Message::setMessageText(const UString& _message)
00127     {
00128         if (mWidgetText != nullptr)
00129             mWidgetText->setCaption(_message);
00130         updateSize();
00131     }
00132 
00133     MessageBoxStyle Message::addButtonName(const UString& _name)
00134     {
00135         //FIXME
00136         if (mVectorButton.size() >= MessageBoxStyle::_CountUserButtons)
00137         {
00138             MYGUI_LOG(Warning, "Too many buttons in message box, ignored");
00139             return MessageBoxStyle::None;
00140         }
00141         // бит, номер кнопки + смещение до Button1
00142         MessageBoxStyle info = MessageBoxStyle(MessageBoxStyle::Enum(MYGUI_FLAG(mVectorButton.size() + MessageBoxStyle::_IndexUserButton1)));
00143 
00144         // запоминаем кнопки для отмены и подтверждения
00145         if (mVectorButton.empty()) mInfoOk = info;
00146         mInfoCancel = info;
00147 
00148         Widget* button = createWidgetT(mButtonType, mButtonSkin, IntCoord(), Align::Left | Align::Bottom);
00149         button->eventMouseButtonClick = newDelegate(this, &Message::notifyButtonClick);
00150         button->setCaption(_name);
00151         button->_setInternalData(info);
00152         mVectorButton.push_back(button);
00153 
00154         updateSize();
00155         return info;
00156     }
00157 
00158     void Message::setMessageIcon(MessageBoxStyle _icon)
00159     {
00160         if (nullptr == mIcon) return;
00161         if (mIcon->getItemResource() != nullptr)
00162         {
00163             mIcon->setItemName( getIconName(_icon.getIconIndex()) );
00164         }
00165         else
00166         {
00167             mIcon->setImageIndex(_icon.getIconIndex());
00168         }
00169 
00170         updateSize();
00171     }
00172 
00173     void Message::setMessageButton(MessageBoxStyle _info)
00174     {
00175         clearButton();
00176 
00177         std::vector<MessageBoxStyle> buttons = _info.getButtons();
00178 
00179         for (size_t index=0; index<buttons.size(); ++index)
00180         {
00181             // корректируем ее номер
00182             MessageBoxStyle info = buttons[index];
00183 
00184             // если бит есть то ставим кнопку
00185             addButtonName(getButtonName(info));
00186 
00187             // внутри адд сбрасывается
00188             mVectorButton.back()->_setInternalData(info);
00189 
00190             // первая кнопка
00191             if (mVectorButton.size() == 1) mInfoOk = info;
00192             // последняя кнопка
00193             mInfoCancel = info;
00194         }
00195 
00196         updateSize();
00197     }
00198 
00199     void Message::setMessageStyle(MessageBoxStyle _style)
00200     {
00201         setMessageButton(_style);
00202         setMessageIcon(_style);
00203     }
00204 
00205     void Message::notifyButtonClick(MyGUI::Widget* _sender)
00206     {
00207         _destroyMessage(*_sender->_getInternalData<MessageBoxStyle>());
00208     }
00209 
00210     void Message::clearButton()
00211     {
00212         for (VectorWidgetPtr::iterator iter=mVectorButton.begin(); iter!=mVectorButton.end(); ++iter)
00213         {
00214             WidgetManager::getInstance().destroyWidget(*iter);
00215         }
00216         mVectorButton.clear();
00217     }
00218 
00219     void Message::onKeyButtonPressed(KeyCode _key, Char _char)
00220     {
00221         Base::onKeyButtonPressed(_key, _char);
00222         if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter)) _destroyMessage(mInfoOk);
00223         else if (_key == KeyCode::Escape) _destroyMessage(mInfoCancel);
00224     }
00225 
00226     void Message::_destroyMessage(MessageBoxStyle _result)
00227     {
00228         eventMessageBoxResult(this, _result);
00229         if (nullptr != mWidgetFade)
00230         {
00231             if (mSmoothShow)
00232             {
00233                 ControllerFadeAlpha* controller = createControllerFadeAlpha(MESSAGE_ALPHA_MIN, MESSAGE_SPEED_COEF, false);
00234                 controller->eventPostAction = newDelegate(action::actionWidgetDestroy);
00235                 ControllerManager::getInstance().addItem(mWidgetFade, controller);
00236             }
00237             else
00238             {
00239                 WidgetManager::getInstance().destroyWidget(mWidgetFade);
00240             }
00241         }
00242         if (mSmoothShow) destroySmooth();
00243         else WidgetManager::getInstance().destroyWidget(this);
00244     }
00245 
00246     void Message::setSmoothShow(bool _smooth)
00247     {
00248         mSmoothShow = _smooth;
00249         if (mSmoothShow)
00250         {
00251             setAlpha(ALPHA_MIN);
00252             setVisible(true);
00253             setVisibleSmooth(true);
00254         }
00255     }
00256 
00257     void Message::setWindowFade(bool _fade)
00258     {
00259         return; //пока пропустим
00260 
00261         if (_fade)
00262         {
00263             if (nullptr == mWidgetFade)
00264             {
00265                 Gui& gui = Gui::getInstance();
00266                 mWidgetFade = gui.createWidgetT(Widget::getClassTypeName(), mFadeSkin, IntCoord(0, 0, gui.getViewSize().width, gui.getViewSize().height), Align::Stretch, mFadeLayer);
00267                 if (mSmoothShow)
00268                 {
00269                     mWidgetFade->setVisible(false);
00270 
00271                     ControllerFadeAlpha* controller = createControllerFadeAlpha(MESSAGE_ALPHA_MAX, MESSAGE_SPEED_COEF, false);
00272                     ControllerManager::getInstance().addItem(mWidgetFade, controller);
00273                 }
00274                 else
00275                 {
00276                     mWidgetFade->setAlpha(MESSAGE_ALPHA_MAX);
00277                 }
00278             }
00279         }
00280         else
00281         {
00282             if (nullptr != mWidgetFade)
00283             {
00284                 WidgetManager::getInstance().destroyWidget(mWidgetFade);
00285                 mWidgetFade = nullptr;
00286             }
00287         }
00288     }
00289 
00290     const char * Message::getIconName(size_t _index)
00291     {
00292         static const size_t CountIcons = 4;
00293         static const char * IconNames[CountIcons + 1] = { "Info", "Quest", "Error", "Warning", "" };
00294         if (_index >= CountIcons) return IconNames[CountIcons];
00295         return IconNames[_index];
00296     }
00297 
00298     MyGUI::Message* Message::createMessageBox(
00299         const std::string& _skin,
00300         const UString& _caption,
00301         const UString& _message,
00302         MessageBoxStyle _style,
00303         const std::string& _layer,
00304         bool _modal,
00305         const std::string& _button1,
00306         const std::string& _button2,
00307         const std::string& _button3,
00308         const std::string& _button4)
00309     {
00310         Message* mess = Gui::getInstance().createWidget<Message>(_skin, IntCoord(), Align::Default, _layer);
00311 
00312         mess->setCaption(_caption);
00313         mess->setMessageText(_message);
00314 
00315         mess->setSmoothShow(true);
00316         if (_modal) mess->setWindowFade(true);
00317 
00318         mess->setMessageStyle(_style);
00319 
00320         if (!_button1.empty())
00321         {
00322             mess->addButtonName(_button1);
00323             if (!_button2.empty())
00324             {
00325                 mess->addButtonName(_button2);
00326                 if (!_button3.empty())
00327                 {
00328                     mess->addButtonName(_button3);
00329                 }
00330             }
00331         }
00332 
00333         if (_layer.empty()) LayerManager::getInstance().attachToLayerNode(mess->getDefaultLayer(), mess);
00334         if (_modal) InputManager::getInstance().addWidgetModal(mess);
00335 
00336         return mess;
00337     }
00338 
00339     void Message::updateSize()
00340     {
00341         ISubWidgetText* text = nullptr;
00342         if (mWidgetText != nullptr)
00343             text = mWidgetText->getSubWidgetText();
00344         IntSize size = text == nullptr ? IntSize() : text->getTextSize();
00345         // минимум высота иконки
00346         if ((nullptr != mIcon) && (mIcon->getImageIndex() != ITEM_NONE))
00347         {
00348             if (size.height < mIcon->getHeight()) size.height = mIcon->getHeight();
00349             size.width += mIcon->getSize().width;
00350         }
00351         size += mOffsetText;
00352         size.width += 3;
00353 
00354         int width = ((int)mVectorButton.size() * mButtonSize.width) + (((int)mVectorButton.size()+1) * mButtonOffset.width);
00355         if (size.width < width) size.width = width;
00356 
00357         int offset = (size.width - width)/2;
00358         offset += mButtonOffset.width;
00359 
00360         const IntSize& view = Gui::getInstance().getViewSize();
00361         setCoord((view.width-size.width)/2, (view.height-size.height)/2, size.width, size.height);
00362 
00363         if (nullptr != mIcon)
00364         {
00365             if (mWidgetText != nullptr)
00366             {
00367                 if (mIcon->getImageIndex() != ITEM_NONE) mWidgetText->setCoord(mLeftOffset2, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight());
00368                 else mWidgetText->setCoord(mLeftOffset1, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight());
00369             }
00370         }
00371 
00372         for (VectorWidgetPtr::iterator iter=mVectorButton.begin(); iter!=mVectorButton.end(); ++iter)
00373         {
00374             (*iter)->setCoord(offset, mCoord.height - mButtonOffset.height, mButtonSize.width, mButtonSize.height);
00375             offset += mButtonOffset.width + mButtonSize.width;
00376         }
00377     }
00378 
00379     ControllerFadeAlpha* Message::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
00380     {
00381         ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
00382         ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
00383 
00384         controller->setAlpha(_alpha);
00385         controller->setCoef(_coef);
00386         controller->setEnabled(_enable);
00387 
00388         return controller;
00389     }
00390 
00391     void Message::setMessageModal(bool _value)
00392     {
00393         if (_value) InputManager::getInstance().addWidgetModal(this);
00394         else InputManager::getInstance().removeWidgetModal(this);
00395     }
00396 
00397     UString Message::getButtonName(MessageBoxStyle _style)
00398     {
00399         size_t index = _style.getButtonIndex();
00400         const char* tag = getButtonTag(index);
00401         UString result = LanguageManager::getInstance().replaceTags(utility::toString("#{", tag, "}"));
00402         if (result == tag) return getButtonName(index);
00403         return result;
00404     }
00405 
00406     const char * Message::getButtonName(size_t _index)
00407     {
00408         static const size_t Count = 9;
00409         static const char * Names[Count + 1] = { "Ok", "Yes", "No", "Abort", "Retry", "Ignore", "Cancel", "Try", "Continue", "" };
00410         if (_index >= Count) return Names[Count];
00411         return Names[_index];
00412     }
00413 
00414     const char * Message::getButtonTag(size_t _index)
00415     {
00416         static const size_t Count = 9;
00417         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", "" };
00418         if (_index >= Count) return Names[Count];
00419         return Names[_index];
00420     }
00421 
00422     void Message::endMessage(MessageBoxStyle _result)
00423     {
00424         _destroyMessage(_result);
00425     }
00426 
00427     void Message::endMessage()
00428     {
00429         _destroyMessage(mInfoCancel);
00430     }
00431 
00432     void Message::setProperty(const std::string& _key, const std::string& _value)
00433     {
00434         if (_key == "Message_Caption") setCaption(_value);
00435         else if (_key == "Message_Message") setMessageText(_value);
00436         else if (_key == "Message_Modal") setMessageModal(utility::parseValue<bool>(_value));
00437         else if (_key == "Message_Button") setMessageButton(utility::parseValue<MessageBoxStyle>(_value));
00438         else if (_key == "Message_AddButton") addButtonName(_value);
00439         else if (_key == "Message_SmoothShow") setSmoothShow(utility::parseValue<bool>(_value));
00440         else if (_key == "Message_Fade") setWindowFade(utility::parseValue<bool>(_value));
00441         else
00442         {
00443             Base::setProperty(_key, _value);
00444             return;
00445         }
00446         eventChangeProperty(this, _key, _value);
00447     }
00448 
00449 } // namespace MyGUI