1 /*! 2 @file 3 @author Albert Semenov 4 @date 12/2010 5 */ 6 #ifndef MESSAGE_BOX_H_ 7 #define MESSAGE_BOX_H_ 8 9 #include <MyGUI.h> 10 #include "MessageBoxStyle.h" 11 #include "BaseLayout/BaseLayout.h" 12 13 namespace MyGUI 14 { 15 class Message; 16 17 typedef delegates::CMultiDelegate2<Message*, MessageBoxStyle> EventHandle_MessageBoxPtrMessageStyle; 18 19 class Message : 20 public wraps::BaseLayout 21 { 22 public: Message()23 Message() : 24 wraps::BaseLayout("MessageBox.layout"), 25 mWidgetText(nullptr), 26 mInfoOk(MessageBoxStyle::None), 27 mInfoCancel(MessageBoxStyle::None), 28 mSmoothShow(false), 29 mIcon(nullptr), 30 mLeftOffset1(0), 31 mLeftOffset2(0) 32 { 33 initialise(); 34 } 35 Message(const std::string & _layoutName)36 Message(const std::string& _layoutName) : 37 wraps::BaseLayout(_layoutName), 38 mWidgetText(nullptr), 39 mInfoOk(MessageBoxStyle::None), 40 mInfoCancel(MessageBoxStyle::None), 41 mSmoothShow(false), 42 mIcon(nullptr), 43 mLeftOffset1(0), 44 mLeftOffset2(0) 45 { 46 initialise(); 47 } 48 ~Message()49 virtual ~Message() 50 { 51 mWidgetText = nullptr; 52 mIcon = nullptr; 53 } 54 55 /** Set caption text*/ setCaption(const UString & _value)56 void setCaption(const UString& _value) 57 { 58 mMainWidget->castType<Window>()->setCaption(_value); 59 } 60 61 /** Set message text*/ setMessageText(const UString & _value)62 void setMessageText(const UString& _value) 63 { 64 if (mWidgetText != nullptr) 65 mWidgetText->setCaption(_value); 66 updateSize(); 67 } 68 69 /** Create button with specific name*/ addButtonName(const UString & _name)70 MessageBoxStyle addButtonName(const UString& _name) 71 { 72 if (mVectorButton.size() >= MessageBoxStyle::_CountUserButtons) 73 { 74 MYGUI_LOG(Warning, "Too many buttons in message box, ignored"); 75 return MessageBoxStyle::None; 76 } 77 // бит, номер кнопки + смещение до Button1 78 MessageBoxStyle info = MessageBoxStyle(MessageBoxStyle::Enum(MYGUI_FLAG(mVectorButton.size() + MessageBoxStyle::_IndexUserButton1))); 79 80 // запоминаем кнопки для отмены и подтверждения 81 if (mVectorButton.empty()) 82 mInfoOk = info; 83 mInfoCancel = info; 84 85 Widget* widget = mMainWidget->createWidgetT(mButtonType, mButtonSkin, IntCoord(), Align::Left | Align::Bottom); 86 Button* button = widget->castType<Button>(); 87 button->eventMouseButtonClick += newDelegate(this, &Message::notifyButtonClick); 88 button->setCaption(_name); 89 button->_setInternalData(info); 90 mVectorButton.push_back(button); 91 92 updateSize(); 93 return info; 94 } 95 96 /** Set smooth message showing*/ setSmoothShow(bool _value)97 void setSmoothShow(bool _value) 98 { 99 mSmoothShow = _value; 100 if (mSmoothShow) 101 { 102 mMainWidget->setAlpha(ALPHA_MIN); 103 mMainWidget->setVisible(true); 104 mMainWidget->castType<Window>()->setVisibleSmooth(true); 105 } 106 } 107 108 /** Set message icon*/ setMessageIcon(MessageBoxStyle _value)109 void setMessageIcon(MessageBoxStyle _value) 110 { 111 if (nullptr == mIcon) 112 return; 113 114 if (mIcon->getItemResource() != nullptr) 115 { 116 mIcon->setItemName(getIconName(_value.getIconIndex())); 117 } 118 else 119 { 120 mIcon->setImageIndex(_value.getIconIndex()); 121 } 122 123 updateSize(); 124 } 125 endMessage(MessageBoxStyle _result)126 void endMessage(MessageBoxStyle _result) 127 { 128 _destroyMessage(_result); 129 } 130 endMessage()131 void endMessage() 132 { 133 _destroyMessage(mInfoCancel); 134 } 135 136 /** Create button using MessageBoxStyle*/ setMessageButton(MessageBoxStyle _value)137 void setMessageButton(MessageBoxStyle _value) 138 { 139 clearButton(); 140 141 std::vector<MessageBoxStyle> buttons = _value.getButtons(); 142 143 for (size_t index = 0; index < buttons.size(); ++index) 144 { 145 // корректируем ее номер 146 MessageBoxStyle info = buttons[index]; 147 148 // если бит есть то ставим кнопку 149 addButtonName(getButtonName(info)); 150 151 // внутри адд сбрасывается 152 mVectorButton.back()->_setInternalData(info); 153 154 // первая кнопка 155 if (mVectorButton.size() == 1) 156 mInfoOk = info; 157 // последняя кнопка 158 mInfoCancel = info; 159 } 160 161 updateSize(); 162 } 163 164 /** Set message style (button and icon)*/ setMessageStyle(MessageBoxStyle _value)165 void setMessageStyle(MessageBoxStyle _value) 166 { 167 setMessageButton(_value); 168 setMessageIcon(_value); 169 } 170 setMessageModal(bool _value)171 void setMessageModal(bool _value) 172 { 173 if (_value) 174 InputManager::getInstance().addWidgetModal(mMainWidget); 175 else 176 InputManager::getInstance().removeWidgetModal(mMainWidget); 177 } 178 179 /** Static method for creating message with one command 180 @param 181 _modal if true all other GUI elements will be blocked untill message is closed 182 @param 183 _style any combination of flags from ViewValueInfo 184 @param 185 _button1 ... _button4 specific buttons names 186 */ 187 static Message* createMessageBox( 188 //const UString& _skinName, 189 const UString& _caption, 190 const UString& _message, 191 MessageBoxStyle _style = MessageBoxStyle::Ok | MessageBoxStyle::IconDefault, 192 const std::string& _layer = "", 193 bool _modal = true, 194 const std::string& _button1 = "", 195 const std::string& _button2 = "", 196 const std::string& _button3 = "", 197 const std::string& _button4 = "") 198 { 199 Message* mess = new Message(); 200 201 mess->setCaption(_caption); 202 mess->setMessageText(_message); 203 204 mess->setSmoothShow(true); 205 206 mess->setMessageStyle(_style); 207 208 if (!_button1.empty()) 209 { 210 mess->addButtonName(_button1); 211 if (!_button2.empty()) 212 { 213 mess->addButtonName(_button2); 214 if (!_button3.empty()) 215 { 216 mess->addButtonName(_button3); 217 } 218 } 219 } 220 221 if (_modal) 222 InputManager::getInstance().addWidgetModal(mess->mMainWidget); 223 224 return mess; 225 } 226 227 /*events:*/ 228 /** Event : button on message window pressed.\n 229 signature : void method(tools::Message* _sender, MessageBoxStyle _result)\n 230 @param _sender widget that called this event 231 @param _result - id of pressed button 232 */ 233 EventHandle_MessageBoxPtrMessageStyle 234 eventMessageBoxResult; 235 236 protected: updateSize()237 void updateSize() 238 { 239 ISubWidgetText* text = nullptr; 240 if (mWidgetText != nullptr) 241 text = mWidgetText->getSubWidgetText(); 242 IntSize size = text == nullptr ? IntSize() : text->getTextSize(); 243 // минимум высота иконки 244 if ((nullptr != mIcon) && (mIcon->getImageIndex() != ITEM_NONE)) 245 { 246 if (size.height < mIcon->getHeight()) 247 size.height = mIcon->getHeight(); 248 size.width += mIcon->getSize().width; 249 } 250 size += mOffsetText; 251 size.width += 3; 252 253 int width = ((int)mVectorButton.size() * mButtonSize.width) + (((int)mVectorButton.size() + 1) * mButtonOffset.width); 254 if (size.width < width) 255 size.width = width; 256 257 int offset = (size.width - width) / 2; 258 offset += mButtonOffset.width; 259 260 size.width += mMainWidget->getWidth() - mMainWidget->getClientCoord().width; 261 size.height += mMainWidget->getHeight() - mMainWidget->getClientCoord().height; 262 263 const IntSize& view = RenderManager::getInstance().getViewSize(); 264 mMainWidget->setCoord((view.width - size.width) / 2, (view.height - size.height) / 2, size.width, size.height); 265 266 if (nullptr != mIcon) 267 { 268 if (mWidgetText != nullptr) 269 { 270 if (mIcon->getImageIndex() != ITEM_NONE) 271 mWidgetText->setCoord(mLeftOffset2, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight()); 272 else 273 mWidgetText->setCoord(mLeftOffset1, mWidgetText->getTop(), mWidgetText->getWidth(), mWidgetText->getHeight()); 274 } 275 } 276 277 for (std::vector<Button*>::iterator iter = mVectorButton.begin(); iter != mVectorButton.end(); ++iter) 278 { 279 (*iter)->setCoord(offset, mMainWidget->getClientCoord().height - mButtonOffset.height, mButtonSize.width, mButtonSize.height); 280 offset += mButtonOffset.width + mButtonSize.width; 281 } 282 } 283 notifyButtonClick(Widget * _sender)284 void notifyButtonClick(Widget* _sender) 285 { 286 _destroyMessage(*_sender->_getInternalData<MessageBoxStyle>()); 287 } 288 clearButton()289 void clearButton() 290 { 291 for (std::vector<Button*>::iterator iter = mVectorButton.begin(); iter != mVectorButton.end(); ++iter) 292 WidgetManager::getInstance().destroyWidget(*iter); 293 mVectorButton.clear(); 294 } 295 296 /*void onKeyButtonPressed(KeyCode _key, Char _char) 297 { 298 Base::onKeyButtonPressed(_key, _char); 299 300 if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter)) 301 _destroyMessage(mInfoOk); 302 else if (_key == KeyCode::Escape) 303 _destroyMessage(mInfoCancel); 304 }*/ 305 _destroyMessage(MessageBoxStyle _result)306 void _destroyMessage(MessageBoxStyle _result) 307 { 308 eventMessageBoxResult(this, _result); 309 310 delete this; 311 } 312 getButtonName(MessageBoxStyle _style)313 UString getButtonName(MessageBoxStyle _style) const 314 { 315 size_t index = _style.getButtonIndex(); 316 const char* tag = getButtonTag(index); 317 UString result = LanguageManager::getInstance().replaceTags(utility::toString("#{", tag, "}")); 318 if (result == tag) 319 return getButtonName(index); 320 return result; 321 } 322 getIconName(size_t _index)323 const char* getIconName(size_t _index) const 324 { 325 static const size_t CountIcons = 4; 326 static const char* IconNames[CountIcons + 1] = { "Info", "Quest", "Error", "Warning", "" }; 327 if (_index >= CountIcons) 328 return IconNames[CountIcons]; 329 return IconNames[_index]; 330 } 331 getButtonName(size_t _index)332 const char* getButtonName(size_t _index) const 333 { 334 static const size_t Count = 9; 335 static const char * Names[Count + 1] = { "Ok", "Yes", "No", "Abort", "Retry", "Ignore", "Cancel", "Try", "Continue", "" }; 336 if (_index >= Count) 337 return Names[Count]; 338 return Names[_index]; 339 } 340 getButtonTag(size_t _index)341 const char* getButtonTag(size_t _index) const 342 { 343 static const size_t Count = 9; 344 static const char* Names[Count + 1] = { "MessageBox_Ok", "MessageBox_Yes", "MessageBox_No", "MessageBox_Abort", "MessageBox_Retry", "MessageBox_Ignore", "MessageBox_Cancel", "MessageBox_Try", "MessageBox_Continue", "" }; 345 if (_index >= Count) 346 return Names[Count]; 347 return Names[_index]; 348 } 349 350 private: initialise()351 void initialise() 352 { 353 assignWidget(mWidgetText, "Text", false); 354 if (mWidgetText != nullptr) 355 { 356 mOffsetText.set(mMainWidget->getClientCoord().width - mWidgetText->getWidth(), mMainWidget->getClientCoord().height - mWidgetText->getHeight()); 357 mLeftOffset2 = mLeftOffset1 = mWidgetText->getLeft(); 358 } 359 360 assignWidget(mIcon, "Icon", false); 361 if (mIcon != nullptr) 362 { 363 mLeftOffset2 = mIcon->getRight() + 3; 364 } 365 366 mButtonType = Button::getClassTypeName(); 367 368 if (mMainWidget->isUserString("ButtonSkin")) 369 mButtonSkin = mMainWidget->getUserString("ButtonSkin"); 370 371 Widget* widget = nullptr; 372 assignWidget(widget, "ButtonPlace", false); 373 if (widget != nullptr) 374 { 375 mButtonOffset.set(widget->getLeft(), mMainWidget->getClientCoord().height - widget->getTop()); 376 widget->setVisible(false); 377 } 378 379 assignWidget(widget, "ButtonTemplate", false); 380 if (widget != nullptr) 381 { 382 mButtonSize = widget->getSize(); 383 } 384 385 Window* window = mMainWidget->castType<Window>(false); 386 if (window != nullptr) 387 window->eventWindowButtonPressed += newDelegate(this, &Message::notifyWindowButtonPressed); 388 } 389 notifyWindowButtonPressed(MyGUI::Window * _sender,const std::string & _name)390 void notifyWindowButtonPressed(MyGUI::Window* _sender, const std::string& _name) 391 { 392 if (_name == "close") 393 endMessage(); 394 } 395 396 private: 397 IntSize mOffsetText; 398 TextBox* mWidgetText; 399 400 std::string mButtonSkin; 401 std::string mButtonType; 402 IntSize mButtonSize; 403 IntSize mButtonOffset; 404 405 std::vector<Button*> mVectorButton; 406 MessageBoxStyle mInfoOk; 407 MessageBoxStyle mInfoCancel; 408 bool mSmoothShow; 409 410 std::string mDefaultCaption; 411 ImageBox* mIcon; 412 int mLeftOffset1; 413 int mLeftOffset2; 414 }; 415 416 } // namespace MyGUI 417 418 #endif // MESSAGE_BOX_H_ 419