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