1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name widgets.cpp - The stratagus ui widgets. */
12 //
13 //      (c) Copyright 2005-2006 by Francois Beerten and Jimmy Salmon
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 //@{
31 
32 /*----------------------------------------------------------------------------
33 --  Includes
34 ----------------------------------------------------------------------------*/
35 
36 #include "stratagus.h"
37 #include "video.h"
38 #include "font.h"
39 //Wyrmgus start
40 #include "grand_strategy.h"
41 //Wyrmgus end
42 #include "cursor.h"
43 #include "ui/ui.h"
44 #include "widgets.h"
45 #include "network.h"
46 #include "netconnect.h"
47 #include "editor.h"
48 #include "sound.h"
49 //Wyrmgus start
50 #include "player.h"
51 //Wyrmgus end
52 //Wyrmgus start
53 #include "results.h"
54 //Wyrmgus end
55 
56 /*----------------------------------------------------------------------------
57 -- Variables
58 ----------------------------------------------------------------------------*/
59 
60 // Guichan stuff we need
61 gcn::Gui *Gui;         /// A Gui object - binds it all together
62 gcn::SDLInput *Input;  /// Input driver
63 
64 static EventCallback GuichanCallbacks;
65 
66 static std::stack<MenuScreen *> MenuStack;
67 
68 /*----------------------------------------------------------------------------
69 --  Functions
70 ----------------------------------------------------------------------------*/
71 
72 
73 //Wyrmgus start
74 //static void MenuHandleButtonDown(unsigned)
MenuHandleButtonDown(unsigned button)75 static void MenuHandleButtonDown(unsigned button)
76 //Wyrmgus end
77 {
78 }
79 //Wyrmgus start
80 //static void MenuHandleButtonUp(unsigned)
MenuHandleButtonUp(unsigned button)81 static void MenuHandleButtonUp(unsigned button)
82 //Wyrmgus end
83 {
84 }
MenuHandleMouseMove(const PixelPos & screenPos)85 static void MenuHandleMouseMove(const PixelPos &screenPos)
86 {
87 	PixelPos pos(screenPos);
88 	HandleCursorMove(&pos.x, &pos.y);
89 }
MenuHandleKeyDown(unsigned key,unsigned keychar)90 static void MenuHandleKeyDown(unsigned key, unsigned keychar)
91 {
92 	HandleKeyModifiersDown(key, keychar);
93 }
MenuHandleKeyUp(unsigned key,unsigned keychar)94 static void MenuHandleKeyUp(unsigned key, unsigned keychar)
95 {
96 	//Wyrmgus start
97 	if (key == 'f') { // ALT+F and CTRL+F toggle fullscreen
98 		if (KeyModifiers & (ModifierAlt | ModifierControl)) {
99 			ToggleFullScreen();
100 			CclCommand("wyr.preferences.VideoFullScreen = Video.FullScreen;");
101 			SavePreferences();
102 		}
103 	/*
104 	} else if (key == 'g') { // ALT+G, CTRL+G grab mouse pointer
105 		if (KeyModifiers & (ModifierAlt | ModifierControl)) {
106 			UiToggleGrabMouse();
107 			CclCommand("wyr.preferences.GrabMouse = GetGrabMouse();");
108 			SavePreferences();
109 		}
110 	*/
111 	}
112 	//Wyrmgus end
113 	HandleKeyModifiersUp(key, keychar);
114 }
MenuHandleKeyRepeat(unsigned key,unsigned keychar)115 static void MenuHandleKeyRepeat(unsigned key, unsigned keychar)
116 {
117 	Input->processKeyRepeat();
118 	HandleKeyModifiersDown(key, keychar);
119 }
120 
121 
122 /**
123 **  Initializes the GUI stuff
124 */
initGuichan()125 void initGuichan()
126 {
127 	gcn::Graphics *graphics;
128 
129 #if defined(USE_OPENGL) || defined(USE_GLES)
130 	if (UseOpenGL) {
131 		graphics = new MyOpenGLGraphics();
132 	} else
133 #endif
134 	{
135 		graphics = new gcn::SDLGraphics();
136 
137 		// Set the target for the graphics object to be the screen.
138 		// In other words, we will draw to the screen.
139 		// Note, any surface will do, it doesn't have to be the screen.
140 		((gcn::SDLGraphics *)graphics)->setTarget(TheScreen);
141 	}
142 
143 	Input = new gcn::SDLInput();
144 
145 	Gui = new gcn::Gui();
146 	Gui->setGraphics(graphics);
147 	Gui->setInput(Input);
148 	Gui->setTop(nullptr);
149 
150 #if defined(USE_OPENGL) || defined(USE_GLES)
151 	Gui->setUseDirtyDrawing(!UseOpenGL);
152 #else
153 	Gui->setUseDirtyDrawing(1);
154 #endif
155 
156 	GuichanCallbacks.ButtonPressed = &MenuHandleButtonDown;
157 	GuichanCallbacks.ButtonReleased = &MenuHandleButtonUp;
158 	GuichanCallbacks.MouseMoved = &MenuHandleMouseMove;
159 	GuichanCallbacks.MouseExit = &HandleMouseExit;
160 	GuichanCallbacks.KeyPressed = &MenuHandleKeyDown;
161 	GuichanCallbacks.KeyReleased = &MenuHandleKeyUp;
162 	GuichanCallbacks.KeyRepeated = &MenuHandleKeyRepeat;
163 	GuichanCallbacks.NetworkEvent = NetworkEvent;
164 }
165 
166 /**
167 **  Free all guichan infrastructure
168 */
freeGuichan()169 void freeGuichan()
170 {
171 	if (Gui) {
172 		delete Gui->getGraphics();
173 		delete Gui;
174 		Gui = nullptr;
175 	}
176 
177 	delete Input;
178 	Input = nullptr;
179 }
180 
181 /**
182 **  Handle input events
183 **
184 **  @param event  event to handle, null if no more events for this frame
185 */
handleInput(const SDL_Event * event)186 void handleInput(const SDL_Event *event)
187 {
188 	if (event) {
189 		if (Input) {
190 			try {
191 				Input->pushInput(*event);
192 			} catch (const gcn::Exception &) {
193 				// ignore unhandled buttons
194 			}
195 		}
196 	} else {
197 		if (Gui) {
198 			Gui->logic();
199 		}
200 	}
201 }
202 
DrawGuichanWidgets()203 void DrawGuichanWidgets()
204 {
205 	if (Gui) {
206 #if defined(USE_OPENGL) || defined(USE_GLES)
207 		Gui->setUseDirtyDrawing(!UseOpenGL && !GameRunning && !Editor.Running);
208 #else
209 		Gui->setUseDirtyDrawing(!GameRunning && !Editor.Running);
210 #endif
211 		Gui->draw();
212 	}
213 }
214 
215 
216 /*----------------------------------------------------------------------------
217 --  LuaActionListener
218 ----------------------------------------------------------------------------*/
219 
220 
221 /**
222 **  LuaActionListener constructor
223 **
224 **  @param l  Lua state
225 **  @param f  Listener function
226 */
LuaActionListener(lua_State * l,lua_Object f)227 LuaActionListener::LuaActionListener(lua_State *l, lua_Object f) :
228 	callback(l, f)
229 {
230 }
231 
232 /**
233 **  Called when an action is received from a Widget. It is used
234 **  to be able to receive a notification that an action has
235 **  occurred.
236 **
237 **  @param eventId  the identifier of the Widget
238 */
action(const std::string & eventId)239 void LuaActionListener::action(const std::string &eventId)
240 {
241 	callback.pushPreamble();
242 	callback.pushString(eventId.c_str());
243 	callback.run();
244 }
245 
246 /**
247 **  LuaActionListener destructor
248 */
~LuaActionListener()249 LuaActionListener::~LuaActionListener()
250 {
251 }
252 
253 #if defined(USE_OPENGL) || defined(USE_GLES)
254 
255 /*----------------------------------------------------------------------------
256 --  MyOpenGLGraphics
257 ----------------------------------------------------------------------------*/
258 
_beginDraw()259 void MyOpenGLGraphics::_beginDraw()
260 {
261 	gcn::Rectangle area(0, 0, Video.Width, Video.Height);
262 	pushClipArea(area);
263 }
264 
_endDraw()265 void MyOpenGLGraphics::_endDraw()
266 {
267 	popClipArea();
268 }
269 
270 //Wyrmgus start
271 //void MyOpenGLGraphics::drawImage(const gcn::Image *image, int srcX, int srcY,
272 //								 int dstX, int dstY, int width, int height)
drawImage(gcn::Image * image,int srcX,int srcY,int dstX,int dstY,int width,int height,int player,unsigned int transparency)273 void MyOpenGLGraphics::drawImage(gcn::Image *image, int srcX, int srcY,
274 								 int dstX, int dstY, int width, int height, int player, unsigned int transparency)
275 //Wyrmgus end
276 {
277 	const gcn::ClipRectangle &r = this->getCurrentClipArea();
278 	int right = std::min<int>(r.x + r.width - 1, Video.Width - 1);
279 	int bottom = std::min<int>(r.y + r.height - 1, Video.Height - 1);
280 
281 	if (r.x > right || r.y > bottom) {
282 		return;
283 	}
284 
285 	PushClipping();
286 	SetClipping(r.x, r.y, right, bottom);
287 	//Wyrmgus start
288 //	((CGraphic *)image)->DrawSubClip(srcX, srcY, width, height,
289 //									 dstX + mClipStack.top().xOffset, dstY + mClipStack.top().yOffset);
290 	if (player != -1) {
291 		((CPlayerColorGraphic *)image)->DrawPlayerColorSubClip(player, srcX, srcY, width, height,
292 										 dstX + mClipStack.top().xOffset, dstY + mClipStack.top().yOffset);
293 	} else {
294 		((CGraphic *)image)->DrawSubClip(srcX, srcY, width, height,
295 										 dstX + mClipStack.top().xOffset, dstY + mClipStack.top().yOffset);
296 	}
297 	//Wyrmgus end
298 	PopClipping();
299 }
300 
drawPoint(int x,int y)301 void MyOpenGLGraphics::drawPoint(int x, int y)
302 {
303 	gcn::Color c = this->getColor();
304 	Video.DrawPixelClip(Video.MapRGBA(0, c.r, c.g, c.b, c.a),
305 						x + mClipStack.top().xOffset, y + mClipStack.top().yOffset);
306 }
307 
drawLine(int x1,int y1,int x2,int y2)308 void MyOpenGLGraphics::drawLine(int x1, int y1, int x2, int y2)
309 {
310 	gcn::Color c = this->getColor();
311 	const PixelPos pos1(x1 + mClipStack.top().xOffset, y1 + mClipStack.top().yOffset);
312 	const PixelPos pos2(x2 + mClipStack.top().xOffset, y2 + mClipStack.top().yOffset);
313 
314 	Video.DrawLineClip(Video.MapRGBA(0, c.r, c.g, c.b, c.a), pos1, pos2);
315 }
316 
drawRectangle(const gcn::Rectangle & rectangle)317 void MyOpenGLGraphics::drawRectangle(const gcn::Rectangle &rectangle)
318 {
319 	gcn::Color c = this->getColor();
320 	if (c.a == 0) {
321 		return;
322 	}
323 
324 	const gcn::ClipRectangle top = mClipStack.top();
325 	gcn::Rectangle area = gcn::Rectangle(rectangle.x + top.xOffset,
326 										 rectangle.y + top.yOffset,
327 										 rectangle.width, rectangle.height);
328 
329 	if (!area.intersect(top)) {
330 		return;
331 	}
332 
333 	int x1 = std::max<int>(area.x, top.x);
334 	int y1 = std::max<int>(area.y, top.y);
335 	int x2 = std::min<int>(area.x + area.width, top.x + top.width);
336 	int y2 = std::min<int>(area.y + area.height, top.y + top.height);
337 
338 	Video.DrawTransRectangle(Video.MapRGB(0, c.r, c.g, c.b),
339 							 x1, y1, x2 - x1, y2 - y1, mColor.a);
340 }
341 
fillRectangle(const gcn::Rectangle & rectangle)342 void MyOpenGLGraphics::fillRectangle(const gcn::Rectangle &rectangle)
343 {
344 	const gcn::Color c = this->getColor();
345 
346 	if (c.a == 0) {
347 		return;
348 	}
349 
350 	const gcn::ClipRectangle top = mClipStack.top();
351 	gcn::Rectangle area = gcn::Rectangle(rectangle.x + top.xOffset,
352 										 rectangle.y + top.yOffset,
353 										 rectangle.width, rectangle.height);
354 
355 	if (!area.intersect(top)) {
356 		return;
357 	}
358 
359 	int x1 = std::max<int>(area.x, top.x);
360 	int y1 = std::max<int>(area.y, top.y);
361 	int x2 = std::min<int>(area.x + area.width, top.x + top.width);
362 	int y2 = std::min<int>(area.y + area.height, top.y + top.height);
363 
364 	Video.FillTransRectangle(Video.MapRGB(0, c.r, c.g, c.b),
365 							 x1, y1, x2 - x1, y2 - y1, c.a);
366 }
367 
368 #endif
369 
370 //Wyrmgus start
371 /*----------------------------------------------------------------------------
372 --  PlayerColorImageWidget
373 ----------------------------------------------------------------------------*/
374 
draw(gcn::Graphics * graphics)375 void PlayerColorImageWidget::draw(gcn::Graphics* graphics)
376 {
377 	int WidgetPlayerColorIndexFromName = GetPlayerColorIndexByName(WidgetPlayerColor);
378 	if (WidgetPlayerColorIndexFromName == -1) {
379 		fprintf(stderr, "Color %s not defined\n", WidgetPlayerColor.c_str());
380 		ExitFatal(1);
381 	}
382 
383 	graphics->drawImage(mImage, ImageOrigin.x, ImageOrigin.y, 0, 0, mImage->getWidth(), mImage->getHeight(), WidgetPlayerColorIndexFromName);
384 }
385 //Wyrmgus end
386 
387 /*----------------------------------------------------------------------------
388 --  ImageButton
389 ----------------------------------------------------------------------------*/
390 
391 
392 /**
393 **  ImageButton constructor
394 */
ImageButton()395 ImageButton::ImageButton() :
396 	Button(), normalImage(nullptr), pressedImage(nullptr),
397 	//Wyrmgus start
398 //	disabledImage(nullptr)
399 	disabledImage(nullptr), frameImage(nullptr), pressedframeImage(nullptr), Transparency(0)
400 	//Wyrmgus end
401 {
402 	setForegroundColor(0xffffff);
403 	//Wyrmgus start
404 	ImageOrigin.x = 0;
405 	ImageOrigin.y = 0;
406 	//Wyrmgus end
407 }
408 
409 /**
410 **  ImageButton constructor
411 **
412 **  @param caption  Caption text
413 */
ImageButton(const std::string & caption)414 ImageButton::ImageButton(const std::string &caption) :
415 	Button(caption), normalImage(nullptr), pressedImage(nullptr),
416 	//Wyrmgus start
417 //	disabledImage(nullptr)
418 	disabledImage(nullptr), frameImage(nullptr), pressedframeImage(nullptr), Transparency(0)
419 	//Wyrmgus end
420 {
421 	setForegroundColor(0xffffff);
422 	//Wyrmgus start
423 	ImageOrigin.x = 0;
424 	ImageOrigin.y = 0;
425 	//Wyrmgus end
426 }
427 
428 /**
429 **  Draw the image button
430 **
431 **  @param graphics  Graphics object to draw with
432 */
draw(gcn::Graphics * graphics)433 void ImageButton::draw(gcn::Graphics *graphics)
434 {
435 	if (!normalImage) {
436 		Button::draw(graphics);
437 		return;
438 	}
439 
440 	gcn::Image *img;
441 
442 	if (!isEnabled()) {
443 		img = disabledImage ? disabledImage : normalImage;
444 	} else if (isPressed()) {
445 		img = pressedImage ? pressedImage : normalImage;
446 	} else if (0 && hasMouse()) {
447 		// FIXME: add mouse-over image
448 		img = nullptr;
449 	} else {
450 		img = normalImage;
451 	}
452 
453 	//Wyrmgus start
454 	if (img) {
455 		if (Transparency) {
456 		#if defined(USE_OPENGL) || defined(USE_GLES)
457 			if (UseOpenGL) {
458 			} else
459 		#endif
460 			{
461 				WidgetGraphicTransparency(int(256 - 2.56 * Transparency), *((CGraphic *)img));
462 			}
463 		}
464 	}
465 
466 //	graphics->drawImage(img, 0, 0, 0, 0,
467 //						img->getWidth(), img->getHeight());
468 
469 	if (frameImage) {
470         graphics->setColor(ColorBlack);
471 		graphics->fillRectangle(gcn::Rectangle((frameImage->getWidth() - img->getWidth()) / 2, (frameImage->getHeight() - img->getHeight()) / 2, img->getWidth(), img->getHeight()));
472 		graphics->drawImage(frameImage, 0, 0, 0, 0,
473 							frameImage->getWidth(), frameImage->getHeight());
474 		if (isPressed()) {
475 			if (Transparency) {
476 			#if defined(USE_OPENGL) || defined(USE_GLES)
477 				if (UseOpenGL) {
478 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
479 					glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
480 				}
481 			#endif
482 			}
483 			graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, ((frameImage->getWidth() - img->getWidth()) / 2) + 1, ((frameImage->getHeight() - img->getHeight()) / 2) + 1,
484 								img->getWidth() - 1, img->getHeight() - 1);
485 			if (Transparency) {
486 			#if defined(USE_OPENGL) || defined(USE_GLES)
487 				if (UseOpenGL) {
488 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
489 				}
490 			#endif
491 			}
492 			if (pressedframeImage) {
493 				graphics->drawImage(pressedframeImage, 0, 0, 0, 0,
494 									pressedframeImage->getWidth(), pressedframeImage->getHeight());
495 			}
496 		} else {
497 			if (Transparency) {
498 			#if defined(USE_OPENGL) || defined(USE_GLES)
499 				if (UseOpenGL) {
500 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
501 					glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
502 				}
503 			#endif
504 			}
505 			graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, (frameImage->getWidth() - img->getWidth()) / 2, (frameImage->getHeight() - img->getHeight()) / 2,
506 								img->getWidth(), img->getHeight());
507 			if (Transparency) {
508 			#if defined(USE_OPENGL) || defined(USE_GLES)
509 				if (UseOpenGL) {
510 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
511 				}
512 			#endif
513 			}
514 		}
515 	} else {
516 		if (Transparency) {
517 		#if defined(USE_OPENGL) || defined(USE_GLES)
518 			if (UseOpenGL) {
519 				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
520 				glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
521 			}
522 		#endif
523 		}
524 		graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, 0, 0,
525 							img->getWidth(), img->getHeight());
526 		if (Transparency) {
527 		#if defined(USE_OPENGL) || defined(USE_GLES)
528 			if (UseOpenGL) {
529 				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
530 			}
531 		#endif
532 		}
533 	}
534 	//Wyrmgus end
535 
536 	graphics->setColor(getForegroundColor());
537 
538 	int textX;
539 	int textY = getHeight() / 2 - getFont()->getHeight() / 2;
540 
541 	switch (getAlignment()) {
542 		case gcn::Graphics::LEFT:
543 			textX = 4;
544 			break;
545 		case gcn::Graphics::CENTER:
546 			textX = getWidth() / 2;
547 			break;
548 		case gcn::Graphics::RIGHT:
549 			textX = getWidth() - 4;
550 			break;
551 		default:
552 			textX = 0;
553 			Assert(!"Unknown alignment.");
554 			//throw GCN_EXCEPTION("Unknown alignment.");
555 	}
556 
557 	graphics->setFont(getFont());
558 	//Wyrmgus start
559 	/*
560 	if (isPressed()) {
561 		graphics->drawText(getCaption(), textX + 4, textY + 4, getAlignment());
562 	} else {
563 		graphics->drawText(getCaption(), textX + 2, textY + 2, getAlignment());
564 	}
565 	*/
566 	bool is_normal = true;
567 	if (hasMouse()) {
568 		is_normal = false;
569 	}
570 	if (isPressed()) {
571 		textX += 4;
572 		textY += 4;
573 		if ((textY + 11) > (getHeight() - 2)) {
574 			textY += (getHeight() - 2) - (textY + 11);
575 		}
576 		if (textY < 1) {
577 			textY = 1;
578 		}
579 	} else {
580 		textX += 2;
581 		textY += 2;
582 		if ((textY + 11) > (getHeight() - 3)) {
583 			textY += (getHeight() - 3) - (textY + 11);
584 		}
585 		if (textY < 0) {
586 			textY = 0;
587 		}
588 	}
589 	graphics->drawText(getCaption(), textX, textY, getAlignment(), is_normal);
590 	//Wyrmgus end
591 
592 	//Wyrmgus start
593 //	if (hasFocus()) {
594 	if (isPressed() && !frameImage) {
595 	//Wyrmgus end
596 		//Wyrmgus start
597 //		graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
598 		if (getWidth() == getHeight() && getWidth() > 64 && getHeight() > 64) {
599 			graphics->drawRectangle(gcn::Rectangle(0 + ((getWidth() - 64) / 2), 0 + ((getHeight() - 64) / 2), getWidth() - (getWidth() - 64), getHeight() - (getHeight() - 64))); //hack to make it appear properly in grand strategy mode
600 		} else {
601 			graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
602 		}
603 		//Wyrmgus end
604 	}
605 
606 	//Wyrmgus start
607 	//restore old alpha
608 #if defined(USE_OPENGL) || defined(USE_GLES)
609 	if (UseOpenGL) {
610 	} else
611 #endif
612 	{
613 		WidgetGraphicTransparency(255, *((CGraphic *)img));
614 	}
615 	//Wyrmgus end
616 }
617 
618 /**
619 **  Automatically adjust the size of an image button
620 */
adjustSize()621 void ImageButton::adjustSize()
622 {
623 	//Wyrmgus start
624 //	if (normalImage) {
625 	if (frameImage) {
626 		setWidth(frameImage->getWidth());
627 		setHeight(frameImage->getHeight());
628 		setPosition(getX(), getY()); //reset position, to make it appropriate for the frame image
629 	} else if (normalImage) {
630 	//Wyrmgus end
631 		setWidth(normalImage->getWidth());
632 		setHeight(normalImage->getHeight());
633 	} else {
634 		Button::adjustSize();
635 	}
636 }
637 
638 //Wyrmgus start
setPosition(int x,int y)639 void ImageButton::setPosition(int x, int y)
640 {
641 	if (frameImage) {
642 		mDimension.x = x - ((frameImage->getWidth() - normalImage->getWidth()) / 2);
643 		mDimension.y = y - ((frameImage->getHeight() - normalImage->getWidth()) / 2);
644 	} else {
645 		mDimension.x = x;
646 		mDimension.y = y;
647 	}
648 }
649 
650 /*----------------------------------------------------------------------------
651 --  PlayerColorImageButtonImageButton
652 ----------------------------------------------------------------------------*/
653 
654 
655 /**
656 **  PlayerColorImageButton constructor
657 */
PlayerColorImageButton()658 PlayerColorImageButton::PlayerColorImageButton() :
659 	Button(), normalImage(nullptr), pressedImage(nullptr),
660 	disabledImage(nullptr), frameImage(nullptr), pressedframeImage(nullptr), ButtonPlayerColor(""), Transparency(0)
661 {
662 	setForegroundColor(0xffffff);
663 	ImageOrigin.x = 0;
664 	ImageOrigin.y = 0;
665 }
666 
667 /**
668 **  PlayerColorImageButton constructor
669 **
670 **  @param caption  Caption text
671 */
PlayerColorImageButton(const std::string & caption,const std::string & playercolor)672 PlayerColorImageButton::PlayerColorImageButton(const std::string &caption, const std::string &playercolor) :
673 	Button(caption), normalImage(nullptr), pressedImage(nullptr),
674 	disabledImage(nullptr), frameImage(nullptr), pressedframeImage(nullptr), ButtonPlayerColor(playercolor), Transparency(0)
675 {
676 	setForegroundColor(0xffffff);
677 	ImageOrigin.x = 0;
678 	ImageOrigin.y = 0;
679 }
680 
681 /**
682 **  Draw the image button
683 **
684 **  @param graphics  Graphics object to draw with
685 */
draw(gcn::Graphics * graphics)686 void PlayerColorImageButton::draw(gcn::Graphics *graphics)
687 {
688 	if (!normalImage) {
689 		Button::draw(graphics);
690 		return;
691 	}
692 
693 	gcn::Image *img;
694 
695 	if (!isEnabled()) {
696 		img = disabledImage ? disabledImage : normalImage;
697 	} else if (isPressed()) {
698 		img = pressedImage ? pressedImage : normalImage;
699 	} else if (0 && hasMouse()) {
700 		// FIXME: add mouse-over image
701 		img = nullptr;
702 	} else {
703 		img = normalImage;
704 	}
705 
706 	int WidgetPlayerColorIndexFromName = GetPlayerColorIndexByName(ButtonPlayerColor);
707 	if (WidgetPlayerColorIndexFromName == -1) {
708 		fprintf(stderr, "Color %s not defined\n", ButtonPlayerColor.c_str());
709 		ExitFatal(1);
710 	}
711 
712 	if (frameImage) {
713         graphics->setColor(ColorBlack);
714 		graphics->fillRectangle(gcn::Rectangle((frameImage->getWidth() - img->getWidth()) / 2, (frameImage->getHeight() - img->getHeight()) / 2, img->getWidth(), img->getHeight()));
715 		graphics->drawImage(frameImage, 0, 0, 0, 0,
716 							frameImage->getWidth(), frameImage->getHeight());
717 		if (isPressed()) {
718 			if (Transparency) {
719 			#if defined(USE_OPENGL) || defined(USE_GLES)
720 				if (UseOpenGL) {
721 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
722 					glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
723 				}
724 			#endif
725 			}
726 			graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, ((frameImage->getWidth() - img->getWidth()) / 2) + 1, ((frameImage->getHeight() - img->getHeight()) / 2) + 1,
727 								img->getWidth() - 1, img->getHeight() - 1, WidgetPlayerColorIndexFromName, Transparency);
728 			if (Transparency) {
729 			#if defined(USE_OPENGL) || defined(USE_GLES)
730 				if (UseOpenGL) {
731 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
732 				}
733 			#endif
734 			}
735 			if (pressedframeImage) {
736 				graphics->drawImage(pressedframeImage, 0, 0, 0, 0,
737 									pressedframeImage->getWidth(), pressedframeImage->getHeight());
738 			}
739 		} else {
740 			if (Transparency) {
741 			#if defined(USE_OPENGL) || defined(USE_GLES)
742 				if (UseOpenGL) {
743 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
744 					glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
745 				}
746 			#endif
747 			}
748 			graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, (frameImage->getWidth() - img->getWidth()) / 2, (frameImage->getHeight() - img->getHeight()) / 2,
749 								img->getWidth(), img->getHeight(), WidgetPlayerColorIndexFromName, Transparency);
750 			if (Transparency) {
751 			#if defined(USE_OPENGL) || defined(USE_GLES)
752 				if (UseOpenGL) {
753 					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
754 				}
755 			#endif
756 			}
757 		}
758 	} else {
759 		if (Transparency) {
760 		#if defined(USE_OPENGL) || defined(USE_GLES)
761 			if (UseOpenGL) {
762 				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
763 				glColor4ub(255, 255, 255, int(256 - 2.56 * Transparency));
764 			}
765 		#endif
766 		}
767 		graphics->drawImage(img, ImageOrigin.x, ImageOrigin.y, 0, 0,
768 							img->getWidth(), img->getHeight(), WidgetPlayerColorIndexFromName, Transparency);
769 		if (Transparency) {
770 		#if defined(USE_OPENGL) || defined(USE_GLES)
771 			if (UseOpenGL) {
772 				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
773 			}
774 		#endif
775 		}
776 	}
777 
778 	graphics->setColor(getForegroundColor());
779 
780 	int textX;
781 	int textY = getHeight() / 2 - getFont()->getHeight() / 2;
782 
783 	switch (getAlignment()) {
784 		case gcn::Graphics::LEFT:
785 			textX = 4;
786 			break;
787 		case gcn::Graphics::CENTER:
788 			textX = getWidth() / 2;
789 			break;
790 		case gcn::Graphics::RIGHT:
791 			textX = getWidth() - 4;
792 			break;
793 		default:
794 			textX = 0;
795 			Assert(!"Unknown alignment.");
796 			//throw GCN_EXCEPTION("Unknown alignment.");
797 	}
798 
799 	graphics->setFont(getFont());
800 	bool is_normal = true;
801 	if (hasMouse()) {
802 		is_normal = false;
803 	}
804 	if (isPressed()) {
805 		graphics->drawText(getCaption(), textX + 4, textY + 4, getAlignment(), is_normal);
806 	} else {
807 		graphics->drawText(getCaption(), textX + 2, textY + 2, getAlignment(), is_normal);
808 	}
809 
810 	if (isPressed() && !frameImage) {
811 //		graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
812 		if (getWidth() == getHeight() && getWidth() > 64 && getHeight() > 64) {
813 			graphics->drawRectangle(gcn::Rectangle(0 + ((getWidth() - 64) / 2), 0 + ((getHeight() - 64) / 2), getWidth() - (getWidth() - 64), getHeight() - (getHeight() - 64))); //hack to make it appear properly in grand strategy mode
814 		} else {
815 			graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
816 		}
817 	}
818 }
819 
820 /**
821 **  Automatically adjust the size of an image button
822 */
adjustSize()823 void PlayerColorImageButton::adjustSize()
824 {
825 	if (frameImage) {
826 		setWidth(frameImage->getWidth());
827 		setHeight(frameImage->getHeight());
828 		setPosition(getX(), getY()); //reset position, to make it appropriate for the frame image
829 	} else if (normalImage) {
830 		setWidth(normalImage->getWidth());
831 		setHeight(normalImage->getHeight());
832 	} else {
833 		Button::adjustSize();
834 	}
835 }
836 
setPosition(int x,int y)837 void PlayerColorImageButton::setPosition(int x, int y)
838 {
839 	if (frameImage) {
840 		mDimension.x = x - ((frameImage->getWidth() - normalImage->getWidth()) / 2);
841 		mDimension.y = y - ((frameImage->getHeight() - normalImage->getWidth()) / 2);
842 	} else {
843 		mDimension.x = x;
844 		mDimension.y = y;
845 	}
846 }
847 
848 /**
849 **  Set transparency.
850 **
851 **  FIXME: use function pointer here.
852 **
853 **  @param player  Pointer to player.
854 **  @param sprite  The sprite in which the colors should be changed.
855 */
WidgetGraphicTransparency(int alpha,const CGraphic & sprite)856 void WidgetGraphicTransparency(int alpha, const CGraphic &sprite)
857 {
858 	SDL_LockSurface(sprite.Surface);
859 //	int oldalpha = Surface->format->alpha;
860 	SDL_SetAlpha(sprite.Surface, SDL_SRCALPHA, alpha);
861 	SDL_UnlockSurface(sprite.Surface);
862 }
863 //Wyrmgus end
864 
865 /*----------------------------------------------------------------------------
866 --  ImageRadioButton
867 ----------------------------------------------------------------------------*/
868 
869 
870 /**
871 **  ImageRadioButton constructor
872 */
ImageRadioButton()873 ImageRadioButton::ImageRadioButton() : gcn::RadioButton(),
874 	uncheckedNormalImage(nullptr), uncheckedPressedImage(nullptr), uncheckedDisabledImage(nullptr),
875 	checkedNormalImage(nullptr), checkedPressedImage(nullptr), checkedDisabledImage(nullptr),
876 	mMouseDown(false)
877 {
878 }
879 
880 /**
881 **  ImageRadioButton constructor
882 */
ImageRadioButton(const std::string & caption,const std::string & group,bool marked)883 ImageRadioButton::ImageRadioButton(const std::string &caption,
884 								   const std::string &group, bool marked) :
885 	gcn::RadioButton(caption, group, marked),
886 	uncheckedNormalImage(nullptr), uncheckedPressedImage(nullptr), uncheckedDisabledImage(nullptr),
887 	checkedNormalImage(nullptr), checkedPressedImage(nullptr), checkedDisabledImage(nullptr),
888 	mMouseDown(false)
889 {
890 }
891 
892 /**
893 **  Draw the image radio button (not the caption)
894 */
drawBox(gcn::Graphics * graphics)895 void ImageRadioButton::drawBox(gcn::Graphics *graphics)
896 {
897 	gcn::Image *img = nullptr;
898 
899 	if (isMarked()) {
900 		if (isEnabled() == false) {
901 			img = checkedDisabledImage;
902 		} else if (mMouseDown) {
903 			img = checkedPressedImage;
904 		} else {
905 			img = checkedNormalImage;
906 		}
907 	} else {
908 		if (isEnabled() == false) {
909 			img = uncheckedDisabledImage;
910 		} else if (mMouseDown) {
911 			img = uncheckedPressedImage;
912 		} else {
913 			img = uncheckedNormalImage;
914 		}
915 	}
916 
917 	if (img) {
918 		graphics->drawImage(img, 0, 0, 0, (getHeight() - img->getHeight()) / 2,
919 							img->getWidth(), img->getHeight());
920 	} else {
921 		RadioButton::drawBox(graphics);
922 	}
923 }
924 
925 /**
926 **  Draw the image radio button
927 */
draw(gcn::Graphics * graphics)928 void ImageRadioButton::draw(gcn::Graphics *graphics)
929 {
930 	drawBox(graphics);
931 
932 	graphics->setFont(getFont());
933 	graphics->setColor(getForegroundColor());
934 
935 	int width;
936 	if (uncheckedNormalImage) {
937 		width = uncheckedNormalImage->getWidth();
938 		width += width / 2;
939 	} else {
940 		width = getHeight();
941 		width += width / 2;
942 	}
943 
944 	graphics->drawText(getCaption(), width - 2, 0);
945 
946 	if (hasFocus()) {
947 		graphics->drawRectangle(gcn::Rectangle(width - 4, 0, getWidth() - width + 3, getHeight()));
948 	}
949 }
950 
951 /**
952 **  Mouse button pressed callback
953 */
mousePress(int,int,int button)954 void ImageRadioButton::mousePress(int, int, int button)
955 {
956 	if (button == gcn::MouseInput::LEFT && hasMouse()) {
957 		mMouseDown = true;
958 	}
959 }
960 
961 /**
962 **  Mouse button released callback
963 */
mouseRelease(int,int,int button)964 void ImageRadioButton::mouseRelease(int, int, int button)
965 {
966 	if (button == gcn::MouseInput::LEFT) {
967 		mMouseDown = false;
968 	}
969 }
970 
971 /**
972 **  Mouse clicked callback
973 */
mouseClick(int,int,int button,int)974 void ImageRadioButton::mouseClick(int, int, int button, int)
975 {
976 	if (button == gcn::MouseInput::LEFT) {
977 		setMarked(true);
978 		generateAction();
979 	}
980 }
981 
982 /**
983 **  Adjusts the size to fit the image and font size
984 */
adjustSize()985 void ImageRadioButton::adjustSize()
986 {
987 	int width, height;
988 
989 	height = getFont()->getHeight();
990 	if (uncheckedNormalImage) {
991 		width = uncheckedNormalImage->getWidth();
992 		width += width / 2;
993 		height = std::max(height, uncheckedNormalImage->getHeight());
994 	} else {
995 		width = getFont()->getHeight();
996 		width += width / 2;
997 	}
998 
999 	setHeight(height);
1000 	setWidth(getFont()->getWidth(mCaption) + width);
1001 }
1002 
1003 
1004 /*----------------------------------------------------------------------------
1005 --  ImageCheckbox
1006 ----------------------------------------------------------------------------*/
1007 
1008 
1009 /**
1010 **  Image checkbox constructor
1011 */
ImageCheckBox()1012 ImageCheckBox::ImageCheckBox() : gcn::CheckBox(),
1013 	uncheckedNormalImage(nullptr), uncheckedPressedImage(nullptr), uncheckedDisabledImage(nullptr),
1014 	checkedNormalImage(nullptr), checkedPressedImage(nullptr), checkedDisabledImage(nullptr),
1015 	mMouseDown(false)
1016 {
1017 }
1018 
1019 /**
1020 **  Image checkbox constructor
1021 */
ImageCheckBox(const std::string & caption,bool marked)1022 ImageCheckBox::ImageCheckBox(const std::string &caption, bool marked) :
1023 	gcn::CheckBox(caption, marked),
1024 	uncheckedNormalImage(nullptr), uncheckedPressedImage(nullptr), uncheckedDisabledImage(nullptr),
1025 	checkedNormalImage(nullptr), checkedPressedImage(nullptr), checkedDisabledImage(nullptr),
1026 	mMouseDown(false)
1027 {
1028 }
1029 
1030 /**
1031 **  Draw the image checkbox
1032 */
draw(gcn::Graphics * graphics)1033 void ImageCheckBox::draw(gcn::Graphics *graphics)
1034 {
1035 	drawBox(graphics);
1036 
1037 	graphics->setFont(getFont());
1038 	graphics->setColor(getForegroundColor());
1039 
1040 	int width;
1041 	if (uncheckedNormalImage) {
1042 		width = uncheckedNormalImage->getWidth();
1043 		width += width / 2;
1044 	} else {
1045 		width = getHeight();
1046 		width += width / 2;
1047 	}
1048 
1049 	graphics->drawText(getCaption(), width - 2, 0);
1050 
1051 	if (hasFocus()) {
1052 		graphics->drawRectangle(gcn::Rectangle(width - 4, 0, getWidth() - width + 3, getHeight()));
1053 	}
1054 }
1055 
1056 /**
1057 **  Draw the checkbox (not the caption)
1058 */
drawBox(gcn::Graphics * graphics)1059 void ImageCheckBox::drawBox(gcn::Graphics *graphics)
1060 {
1061 	gcn::Image *img = nullptr;
1062 
1063 	if (mMarked) {
1064 		if (isEnabled() == false) {
1065 			img = checkedDisabledImage;
1066 		} else if (mMouseDown) {
1067 			img = checkedPressedImage;
1068 		} else {
1069 			img = checkedNormalImage;
1070 		}
1071 	} else {
1072 		if (isEnabled() == false) {
1073 			img = uncheckedDisabledImage;
1074 		} else if (mMouseDown) {
1075 			img = uncheckedPressedImage;
1076 		} else {
1077 			img = uncheckedNormalImage;
1078 		}
1079 	}
1080 
1081 	if (img) {
1082 		graphics->drawImage(img, 0, 0, 0, (getHeight() - img->getHeight()) / 2,
1083 							img->getWidth(), img->getHeight());
1084 	} else {
1085 		CheckBox::drawBox(graphics);
1086 	}
1087 }
1088 
1089 /**
1090 **  Mouse button pressed callback
1091 */
mousePress(int,int,int button)1092 void ImageCheckBox::mousePress(int, int, int button)
1093 {
1094 	if (button == gcn::MouseInput::LEFT && hasMouse()) {
1095 		mMouseDown = true;
1096 	}
1097 }
1098 
1099 /**
1100 **  Mouse button released callback
1101 */
mouseRelease(int,int,int button)1102 void ImageCheckBox::mouseRelease(int, int, int button)
1103 {
1104 	if (button == gcn::MouseInput::LEFT) {
1105 		mMouseDown = false;
1106 	}
1107 }
1108 
1109 /**
1110 **  Mouse clicked callback
1111 */
mouseClick(int,int,int button,int)1112 void ImageCheckBox::mouseClick(int, int, int button, int)
1113 {
1114 	if (button == gcn::MouseInput::LEFT) {
1115 		toggle();
1116 	}
1117 }
1118 
1119 /**
1120 **  Adjusts the size to fit the image and font size
1121 */
adjustSize()1122 void ImageCheckBox::adjustSize()
1123 {
1124 	int width, height;
1125 
1126 	height = getFont()->getHeight();
1127 	if (uncheckedNormalImage) {
1128 		width = uncheckedNormalImage->getWidth();
1129 		width += width / 2;
1130 		height = std::max(height, uncheckedNormalImage->getHeight());
1131 	} else {
1132 		width = getFont()->getHeight();
1133 		width += width / 2;
1134 	}
1135 
1136 	setHeight(height);
1137 	setWidth(getFont()->getWidth(mCaption) + width);
1138 }
1139 
1140 
1141 /*----------------------------------------------------------------------------
1142 --  ImageSlider
1143 ----------------------------------------------------------------------------*/
1144 
1145 
1146 /**
1147 **  Image slider constructor
1148 */
ImageSlider(double scaleEnd)1149 ImageSlider::ImageSlider(double scaleEnd) :
1150 	Slider(scaleEnd), markerImage(nullptr), backgroundImage(nullptr), disabledBackgroundImage(nullptr)
1151 {
1152 }
1153 
1154 /**
1155 **  Image slider constructor
1156 */
ImageSlider(double scaleStart,double scaleEnd)1157 ImageSlider::ImageSlider(double scaleStart, double scaleEnd) :
1158 	Slider(scaleStart, scaleEnd), markerImage(nullptr), backgroundImage(nullptr), disabledBackgroundImage(nullptr)
1159 {
1160 }
1161 
1162 /**
1163 **  Draw the image slider marker
1164 */
drawMarker(gcn::Graphics * graphics)1165 void ImageSlider::drawMarker(gcn::Graphics *graphics)
1166 {
1167 	gcn::Image *img = markerImage;
1168 
1169 	if (isEnabled()) {
1170 		if (img) {
1171 			if (getOrientation() == HORIZONTAL) {
1172 				int v = getMarkerPosition();
1173 				graphics->drawImage(img, 0, 0, v, 0,
1174 					img->getWidth(), img->getHeight());
1175 			} else {
1176 				int v = (getHeight() - getMarkerLength()) - getMarkerPosition();
1177 				graphics->drawImage(img, 0, 0, 0, v,
1178 					img->getWidth(), img->getHeight());
1179 			}
1180 		} else {
1181 			Slider::drawMarker(graphics);
1182 		}
1183 	}
1184 }
1185 
1186 /**
1187 **  Draw the image slider
1188 */
draw(gcn::Graphics * graphics)1189 void ImageSlider::draw(gcn::Graphics *graphics)
1190 {
1191 	gcn::Image *img = nullptr;
1192 
1193 	if (isEnabled()) {
1194 		img = backgroundImage;
1195 	} else {
1196 		img = disabledBackgroundImage;
1197 	}
1198 
1199 	if (img) {
1200 		graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
1201 		if (isEnabled()) {
1202 			drawMarker(graphics);
1203 		}
1204 	} else {
1205 		Slider::draw(graphics);
1206 	}
1207 }
1208 
1209 /**
1210 **  Set the marker image
1211 */
setMarkerImage(gcn::Image * image)1212 void ImageSlider::setMarkerImage(gcn::Image *image)
1213 {
1214 	markerImage = image;
1215 	setMarkerLength(image->getWidth());
1216 }
1217 
1218 /**
1219 **  Set the background image
1220 */
setBackgroundImage(gcn::Image * image)1221 void ImageSlider::setBackgroundImage(gcn::Image *image)
1222 {
1223 	backgroundImage = image;
1224 }
1225 
1226 /**
1227 **  Set the disabled background image
1228 */
setDisabledBackgroundImage(gcn::Image * image)1229 void ImageSlider::setDisabledBackgroundImage(gcn::Image *image)
1230 {
1231 	disabledBackgroundImage = image;
1232 }
1233 
1234 
1235 /*----------------------------------------------------------------------------
1236 --  MultiLineLabel
1237 ----------------------------------------------------------------------------*/
1238 
1239 
1240 /**
1241 **  MultiLineLabel constructor
1242 */
MultiLineLabel()1243 MultiLineLabel::MultiLineLabel()
1244 {
1245 	this->mAlignment = LEFT;
1246 	this->mVerticalAlignment = TOP;
1247 	this->mLineWidth = 0;
1248 }
1249 
1250 /**
1251 **  MultiLineLabel constructor
1252 */
MultiLineLabel(const std::string & caption)1253 MultiLineLabel::MultiLineLabel(const std::string &caption)
1254 {
1255 	this->mCaption = caption;
1256 	this->mAlignment = LEFT;
1257 	this->mVerticalAlignment = TOP;
1258 
1259 	this->mLineWidth = 999999;
1260 	this->wordWrap();
1261 	this->adjustSize();
1262 }
1263 
1264 /**
1265 **  Set the caption
1266 */
setCaption(const std::string & caption)1267 void MultiLineLabel::setCaption(const std::string &caption)
1268 {
1269 	this->mCaption = caption;
1270 	this->wordWrap();
1271 	this->setDirty(true);
1272 }
1273 
1274 /**
1275 **  Get the caption
1276 */
getCaption() const1277 const std::string &MultiLineLabel::getCaption() const
1278 {
1279 	return this->mCaption;
1280 }
1281 
1282 /**
1283 **  Set the horizontal alignment
1284 */
setAlignment(unsigned int alignment)1285 void MultiLineLabel::setAlignment(unsigned int alignment)
1286 {
1287 	this->mAlignment = alignment;
1288 }
1289 
1290 /**
1291 **  Get the horizontal alignment
1292 */
getAlignment()1293 unsigned int MultiLineLabel::getAlignment()
1294 {
1295 	return this->mAlignment;
1296 }
1297 
1298 /**
1299 **  Set the vertical alignment
1300 */
setVerticalAlignment(unsigned int alignment)1301 void MultiLineLabel::setVerticalAlignment(unsigned int alignment)
1302 {
1303 	this->mVerticalAlignment = alignment;
1304 }
1305 
1306 /**
1307 **  Get the vertical alignment
1308 */
getVerticalAlignment()1309 unsigned int MultiLineLabel::getVerticalAlignment()
1310 {
1311 	return this->mVerticalAlignment;
1312 }
1313 
1314 /**
1315 **  Set the line width
1316 */
setLineWidth(int width)1317 void MultiLineLabel::setLineWidth(int width)
1318 {
1319 	this->mLineWidth = width;
1320 	this->wordWrap();
1321 }
1322 
1323 /**
1324 **  Get the line width
1325 */
getLineWidth()1326 int MultiLineLabel::getLineWidth()
1327 {
1328 	return this->mLineWidth;
1329 }
1330 
1331 /**
1332 **  Adjust the size
1333 */
adjustSize()1334 void MultiLineLabel::adjustSize()
1335 {
1336 	int width = 0;
1337 	for (int i = 0; i < (int)this->mTextRows.size(); ++i) {
1338 		int w = this->getFont()->getWidth(this->mTextRows[i]);
1339 		if (width < w) {
1340 			width = std::min(w, this->mLineWidth);
1341 		}
1342 	}
1343 	this->setWidth(width);
1344 	this->setHeight(this->getFont()->getHeight() * this->mTextRows.size());
1345 }
1346 
1347 /**
1348 **  Draw the label
1349 */
draw(gcn::Graphics * graphics)1350 void MultiLineLabel::draw(gcn::Graphics *graphics)
1351 {
1352 	graphics->setFont(getFont());
1353 	graphics->setColor(getForegroundColor());
1354 
1355 	int textX, textY;
1356 	switch (this->getAlignment()) {
1357 		case LEFT:
1358 			textX = 0;
1359 			break;
1360 		case CENTER:
1361 			textX = this->getWidth() / 2;
1362 			break;
1363 		case RIGHT:
1364 			textX = this->getWidth();
1365 			break;
1366 		default:
1367 			textX = 0;
1368 			Assert(!"Unknown alignment.");
1369 			//throw GCN_EXCEPTION("Unknown alignment.");
1370 	}
1371 	switch (this->getVerticalAlignment()) {
1372 		case TOP:
1373 			textY = 0;
1374 			break;
1375 		case CENTER:
1376 			textY = (this->getHeight() - (int)this->mTextRows.size() * this->getFont()->getHeight()) / 2;
1377 			break;
1378 		case BOTTOM:
1379 			textY = this->getHeight() - (int)this->mTextRows.size() * this->getFont()->getHeight();
1380 			break;
1381 		default:
1382 			textY = 0;
1383 			Assert(!"Unknown alignment.");
1384 			//throw GCN_EXCEPTION("Unknown alignment.");
1385 	}
1386 
1387 	for (int i = 0; i < (int)this->mTextRows.size(); ++i) {
1388 		graphics->drawText(this->mTextRows[i], textX, textY + i * this->getFont()->getHeight(),
1389 						   this->getAlignment());
1390 	}
1391 }
1392 
1393 /**
1394 **  Draw the border
1395 */
drawBorder(gcn::Graphics * graphics)1396 void MultiLineLabel::drawBorder(gcn::Graphics *graphics)
1397 {
1398 	gcn::Color faceColor = getBaseColor();
1399 	gcn::Color highlightColor, shadowColor;
1400 	int alpha = getBaseColor().a;
1401 	int width = getWidth() + getBorderSize() * 2 - 1;
1402 	int height = getHeight() + getBorderSize() * 2 - 1;
1403 	highlightColor = faceColor + 0x303030;
1404 	highlightColor.a = alpha;
1405 	shadowColor = faceColor - 0x303030;
1406 	shadowColor.a = alpha;
1407 
1408 	for (unsigned int i = 0; i < getBorderSize(); ++i) {
1409 		graphics->setColor(shadowColor);
1410 		graphics->drawLine(i, i, width - i, i);
1411 		graphics->drawLine(i, i + 1, i, height - i - 1);
1412 		graphics->setColor(highlightColor);
1413 		graphics->drawLine(width - i, i + 1, width - i, height - i);
1414 		graphics->drawLine(i, height - i, width - i - 1, height - i);
1415 	}
1416 }
1417 
1418 /**
1419 **  Do word wrap
1420 */
wordWrap()1421 void MultiLineLabel::wordWrap()
1422 {
1423 	gcn::Font *font = this->getFont();
1424 	int lineWidth = this->getLineWidth();
1425 	std::string str = this->getCaption();
1426 	size_t pos, lastPos;
1427 	std::string substr;
1428 	bool done = false;
1429 	bool first = true;
1430 
1431 	this->mTextRows.clear();
1432 
1433 	while (!done) {
1434 		if (str.find('\n') != std::string::npos || font->getWidth(str) > lineWidth) {
1435 			// string too wide or has a newline, split it up
1436 			first = true;
1437 			lastPos = 0;
1438 			while (1) {
1439 				// look for any whitespace
1440 				pos = str.find_first_of(" \t\n", first ? 0 : lastPos + 1);
1441 				if (pos != std::string::npos) {
1442 					// found space, now check width
1443 					substr = str.substr(0, pos);
1444 					if (font->getWidth(substr) > lineWidth) {
1445 						// sub-string is too big, use last good position
1446 						if (first) {
1447 							// didn't find a good last position
1448 							substr = str.substr(0, pos);
1449 							this->mTextRows.push_back(substr);
1450 							str = str.substr(pos + 1);
1451 							break;
1452 						} else {
1453 							substr = str.substr(0, lastPos);
1454 							this->mTextRows.push_back(substr);
1455 							// If we stopped at a space then skip any extra spaces but stop at a newline
1456 							if (str[lastPos] != '\n') {
1457 								while (str[lastPos + 1] == ' ' || str[lastPos + 1] == '\t' || str[lastPos + 1] == '\n') {
1458 									++lastPos;
1459 									if (str[lastPos] == '\n') {
1460 										break;
1461 									}
1462 								}
1463 							}
1464 							str = str.substr(lastPos + 1);
1465 							break;
1466 						}
1467 					} else {
1468 						// sub-string is small enough
1469 						// stop if we found a newline, otherwise look for next space
1470 						if (str[pos] == '\n') {
1471 							substr = str.substr(0, pos);
1472 							this->mTextRows.push_back(substr);
1473 							str = str.substr(pos + 1);
1474 							break;
1475 						}
1476 					}
1477 				} else {
1478 					// no space found
1479 					if (first) {
1480 						// didn't find a good last position, we're done
1481 						this->mTextRows.push_back(str);
1482 						done = true;
1483 						break;
1484 					} else {
1485 						substr = str.substr(0, lastPos);
1486 						this->mTextRows.push_back(substr);
1487 						str = str.substr(lastPos + 1);
1488 						break;
1489 					}
1490 				}
1491 				lastPos = pos;
1492 				first = false;
1493 			}
1494 		} else {
1495 			// string small enough
1496 			this->mTextRows.push_back(str);
1497 			done = true;
1498 		}
1499 	}
1500 }
1501 
1502 
1503 /*----------------------------------------------------------------------------
1504 --  ScrollingWidget
1505 ----------------------------------------------------------------------------*/
1506 
1507 
1508 /**
1509 **  ScrollingWidget constructor.
1510 **
1511 **  @param width   Width of the widget.
1512 **  @param height  Height of the widget.
1513 */
ScrollingWidget(int width,int height)1514 ScrollingWidget::ScrollingWidget(int width, int height) :
1515 	gcn::ScrollArea(nullptr, gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_NEVER),
1516 	speedY(1.f), containerY(0.f), finished(false)
1517 {
1518 	container.setDimension(gcn::Rectangle(0, 0, width, height));
1519 	container.setOpaque(false);
1520 	setContent(&container);
1521 	setDimension(gcn::Rectangle(0, 0, width, height));
1522 }
1523 
1524 /**
1525 **  Add a widget in the window.
1526 **
1527 **  @param widget  Widget to add.
1528 **  @param x       Position of the widget in the window.
1529 **  @param y       Position of the widget in the window.
1530 */
add(gcn::Widget * widget,int x,int y)1531 void ScrollingWidget::add(gcn::Widget *widget, int x, int y)
1532 {
1533 	container.add(widget, x, y);
1534 	if (x + widget->getWidth() > container.getWidth()) {
1535 		container.setWidth(x + widget->getWidth());
1536 	}
1537 	if (y + widget->getHeight() > container.getHeight()) {
1538 		container.setHeight(y + widget->getHeight());
1539 	}
1540 }
1541 
1542 /**
1543 **  Scrolling the content when possible.
1544 */
logic()1545 void ScrollingWidget::logic()
1546 {
1547 	setDirty(true);
1548 	if (container.getHeight() + containerY - speedY > 0) {
1549 		// the bottom of the container is lower than the top
1550 		// of the widget. It is thus still visible.
1551 		containerY -= speedY;
1552 		container.setY((int)containerY);
1553 	} else if (!finished) {
1554 		finished = true;
1555 		generateAction();
1556 	}
1557 }
1558 
1559 /**
1560 **  Restart animation to the beginning.
1561 */
restart()1562 void ScrollingWidget::restart()
1563 {
1564 	container.setY(0);
1565 	containerY = 0.f;
1566 	finished = (container.getHeight() == getHeight());
1567 }
1568 
1569 
1570 /*----------------------------------------------------------------------------
1571 --  Windows
1572 ----------------------------------------------------------------------------*/
1573 
1574 
1575 /**
1576 **  Windows constructor.
1577 **
1578 **  @param title   Title of the window.
1579 **  @param width   Width of the window.
1580 **  @param height  Height of the window.
1581 */
Windows(const std::string & title,int width,int height)1582 Windows::Windows(const std::string &title, int width, int height) :
1583 	Window(title), blockwholewindow(true)
1584 {
1585 	container.setDimension(gcn::Rectangle(0, 0, width, height));
1586 	scroll.setDimension(gcn::Rectangle(0, 0, width, height));
1587 	this->setContent(&scroll);
1588 	scroll.setContent(&container);
1589 	this->resizeToContent();
1590 }
1591 
1592 /**
1593 **  Add a widget in the window.
1594 **
1595 **  @param widget  Widget to add.
1596 **  @param x       Position of the widget in the window.
1597 **  @param y       Position of the widget in the window.
1598 */
add(gcn::Widget * widget,int x,int y)1599 void Windows::add(gcn::Widget *widget, int x, int y)
1600 {
1601 	container.add(widget, x, y);
1602 	if (x + widget->getWidth() > container.getWidth()) {
1603 		container.setWidth(x + widget->getWidth());
1604 	}
1605 	if (y + widget->getHeight() > container.getHeight()) {
1606 		container.setHeight(y + widget->getHeight());
1607 	}
1608 }
1609 
1610 /**
1611 **  Move the window when it is dragged.
1612 **
1613 **  @param x   X coordinate of the mouse relative to the window.
1614 **  @param y   Y coordinate of the mouse relative to the widndow.
1615 **
1616 **  @note Once dragged, without release the mouse,
1617 **    if you go virtually outside the container then go back,
1618 **    you have to wait the virtual cursor are in the container.
1619 **    It is because x, y argument refer to a virtual cursor :(
1620 **  @note An another thing is strange
1621 **    when the container is a "scrollable" ScrollArea with the cursor.
1622 **    The cursor can go outside the visual area.
1623 */
mouseMotion(int x,int y)1624 void Windows::mouseMotion(int x, int y)
1625 {
1626 	gcn::BasicContainer *bcontainer = getParent();
1627 	int diffx;
1628 	int diffy;
1629 	int criticalx;
1630 	int criticaly;
1631 	int absx;
1632 	int absy;
1633 
1634 	if (!mMouseDrag || !isMovable()) {
1635 		return;
1636 	}
1637 
1638 	diffx = x - mMouseXOffset;
1639 	diffy = y - mMouseYOffset;
1640 	if (blockwholewindow) {
1641 		criticalx = getX();
1642 		criticaly = getY();
1643 	} else {
1644 		criticalx = getX() + mMouseXOffset;
1645 		criticaly = getY() + mMouseYOffset;
1646 	}
1647 
1648 
1649 	if (criticalx + diffx < 0) {
1650 		diffx = -criticalx;
1651 	}
1652 	if (criticaly + diffy < 0) {
1653 		diffy = -criticaly;
1654 	}
1655 
1656 	if (blockwholewindow) {
1657 		criticalx = getX() + getWidth();
1658 		criticaly = getY() + getHeight();
1659 	}
1660 	if (criticalx + diffx >= bcontainer->getWidth()) {
1661 		diffx = bcontainer->getWidth() - criticalx;
1662 	}
1663 	if (criticaly + diffy >= bcontainer->getHeight()) {
1664 		diffy = bcontainer->getHeight() - criticaly;
1665 	}
1666 
1667 	// Place the window.
1668 	x = getX() + diffx;
1669 	y = getY() + diffy;
1670 	setPosition(x, y);
1671 
1672 	// Move the cursor.
1673 	// Useful only when window reachs the limit.
1674 	getAbsolutePosition(absx, absy);
1675 	CursorScreenPos.x = absx + mMouseXOffset;
1676 	CursorScreenPos.y = absy + mMouseYOffset;
1677 }
1678 
1679 /**
1680 **  Set background color of the window.
1681 **
1682 **  @param color  Color to set.
1683 */
setBackgroundColor(const gcn::Color & color)1684 void Windows::setBackgroundColor(const gcn::Color &color)
1685 {
1686 	Window::setBackgroundColor(color);
1687 	scroll.setBackgroundColor(color);
1688 }
1689 
1690 /**
1691 **  Set base color of the windows.
1692 **
1693 **  @param color  Color to set.
1694 */
setBaseColor(const gcn::Color & color)1695 void Windows::setBaseColor(const gcn::Color &color)
1696 {
1697 	Window::setBaseColor(color);
1698 	container.setBaseColor(color);
1699 }
1700 
1701 /*----------------------------------------------------------------------------
1702 --  ImageTextField
1703 ----------------------------------------------------------------------------*/
1704 
draw(gcn::Graphics * graphics)1705 void ImageTextField::draw(gcn::Graphics *graphics)
1706 {
1707 	gcn::Font *font;
1708 	int x, y;
1709 	CGraphic *img = this->itemImage;
1710 	if (!img) {
1711 		fprintf(stderr, "Not all graphics for ImageTextField were set\n");
1712 		ExitFatal(1);
1713 	}
1714 	img->Resize(getWidth(), img->getHeight());
1715 	graphics->drawImage(img, 0, 0, 0, 0, getWidth(), img->getHeight());
1716 
1717 	if (hasFocus())
1718 	{
1719 		drawCaret(graphics, getFont()->getWidth(mText.substr(0, mCaretPosition)) - mXScroll);
1720 	}
1721 
1722 	graphics->setColor(getForegroundColor());
1723 	font = getFont();
1724 	graphics->setFont(font);
1725 
1726 	x = 1 - mXScroll;
1727 	y = 1;
1728 
1729 	if (mSelectEndOffset != 0)
1730 	{
1731 		unsigned int first;
1732 		unsigned int len;
1733 		int selX;
1734 		int selW;
1735 		std::string tmpStr;
1736 
1737 		getTextSelectionPositions(&first, &len);
1738 
1739 		tmpStr = std::string(mText.substr(0, first));
1740 		selX = font->getWidth(tmpStr);
1741 
1742 		tmpStr = std::string(mText.substr(first, len));
1743 		selW = font->getWidth(tmpStr);
1744 
1745 		graphics->setColor(gcn::Color(127, 127, 127));
1746 		graphics->fillRectangle(gcn::Rectangle(x + selX, y, selW, font->getHeight()));
1747 	}
1748 
1749 	graphics->drawText(mText, x, y);
1750 }
1751 
drawBorder(gcn::Graphics * graphics)1752 void ImageTextField::drawBorder(gcn::Graphics *graphics)
1753 {
1754 	gcn::Color faceColor = getBaseColor();
1755 	gcn::Color highlightColor, shadowColor;
1756 	int alpha = getBaseColor().a;
1757 	int width = getWidth() + getBorderSize() * 2 - 1;
1758 	int height = getHeight() + getBorderSize() * 2 - 1;
1759 	height = itemImage ? std::max<int>(height, itemImage->getHeight()) : height;
1760 	highlightColor = faceColor + 0x303030;
1761 	highlightColor.a = alpha;
1762 	shadowColor = faceColor - 0x303030;
1763 	shadowColor.a = alpha;
1764 
1765 	unsigned int i;
1766 	for (i = 0; i < getBorderSize(); ++i)
1767 	{
1768 		graphics->setColor(shadowColor);
1769 		graphics->drawLine(i,i, width - i, i);
1770 		graphics->drawLine(i,i + 1, i, height - i - 1);
1771 		graphics->setColor(highlightColor);
1772 		graphics->drawLine(width - i,i + 1, width - i, height - i);
1773 		graphics->drawLine(i,height - i, width - i - 1, height - i);
1774 	}
1775 }
1776 
1777 /*----------------------------------------------------------------------------
1778 --  LuaListModel
1779 ----------------------------------------------------------------------------*/
1780 
1781 
1782 /**
1783 **  Set the list
1784 */
setList(lua_State * lua,lua_Object * lo)1785 void LuaListModel::setList(lua_State *lua, lua_Object *lo)
1786 {
1787 	list.clear();
1788 
1789 	const int args = lua_rawlen(lua, *lo);
1790 	for (int j = 0; j < args; ++j) {
1791 		list.push_back(std::string(LuaToString(lua, *lo, j + 1)));
1792 	}
1793 }
1794 
1795 /*----------------------------------------------------------------------------
1796 --  ImageListBox
1797 ----------------------------------------------------------------------------*/
1798 
ImageListBox()1799 ImageListBox::ImageListBox() : gcn::ListBox(), itemImage(nullptr)
1800 {
1801 }
1802 
ImageListBox(gcn::ListModel * listModel)1803 ImageListBox::ImageListBox(gcn::ListModel *listModel) : gcn::ListBox(listModel), itemImage(nullptr)
1804 {
1805 }
1806 
draw(gcn::Graphics * graphics)1807 void ImageListBox::draw(gcn::Graphics *graphics)
1808 {
1809 	if (mListModel == nullptr) {
1810 		return;
1811 	}
1812 
1813 	graphics->setColor(getForegroundColor());
1814 	graphics->setFont(getFont());
1815 
1816 	int i, fontHeight;
1817 	int y = 0;
1818 	CGraphic *img = itemImage;
1819 	//Wyrmgus start
1820 //	img->Resize(getWidth(), img->getHeight());
1821 	//Wyrmgus end
1822 
1823 	fontHeight = std::max<int>(getFont()->getHeight(), img->getHeight());
1824 
1825     /**
1826         * @todo Check cliprects so we do not have to iterate over elements in the list model
1827         */
1828 	for (i = 0; i < mListModel->getNumberOfElements(); ++i) {
1829 		graphics->drawImage(img, 0, 0, 0, y, getWidth(), img->getHeight());
1830 		if (i == mSelected) {
1831 			graphics->drawText("~<" + mListModel->getElementAt(i) + "~>", 1, y + (fontHeight - getFont()->getHeight()) / 2);
1832 		} else {
1833 			graphics->drawText(mListModel->getElementAt(i), 1, y + (fontHeight - getFont()->getHeight()) / 2);
1834 		}
1835 
1836 		y += fontHeight;
1837 	}
1838 	img->SetOriginalSize();
1839 }
1840 
drawBorder(gcn::Graphics * graphics)1841 void ImageListBox::drawBorder(gcn::Graphics *graphics)
1842 {
1843 	gcn::Color faceColor = getBaseColor();
1844 	gcn::Color highlightColor, shadowColor;
1845 	int alpha = getBaseColor().a;
1846 	int width = getWidth() + getBorderSize() * 2 - 1;
1847 	int height = getHeight() + getBorderSize() * 2 - 1;
1848 	highlightColor = faceColor + 0x303030;
1849 	highlightColor.a = alpha;
1850 	shadowColor = faceColor - 0x303030;
1851 	shadowColor.a = alpha;
1852 
1853 	unsigned int i;
1854 	for (i = 0; i < getBorderSize(); ++i)
1855 	{
1856 		graphics->setColor(shadowColor);
1857 		graphics->drawLine(i,i, width - i, i);
1858 		graphics->drawLine(i,i + 1, i, height - i - 1);
1859 		graphics->setColor(highlightColor);
1860 		graphics->drawLine(width - i,i + 1, width - i, height - i);
1861 		graphics->drawLine(i,height - i, width - i - 1, height - i);
1862 	}
1863 }
1864 
adjustSize()1865 void ImageListBox::adjustSize()
1866 {
1867 	if (mListModel != nullptr)
1868 	{
1869 		setHeight((itemImage ? std::max<int>(getFont()->getHeight(), itemImage->getHeight()) : getFont()->getHeight()) * mListModel->getNumberOfElements());
1870 	}
1871 }
1872 
mousePress(int,int y,int button)1873 void ImageListBox::mousePress(int, int y, int button)
1874 {
1875 	if (button == gcn::MouseInput::LEFT && hasMouse())
1876 	{
1877 		setSelected(y / (itemImage ? std::max<int>(getFont()->getHeight(), itemImage->getHeight()) : getFont()->getHeight()));
1878 		generateAction();
1879 	}
1880 }
1881 
setSelected(int selected)1882 void ImageListBox::setSelected(int selected)
1883 {
1884 	if (mListModel == nullptr)
1885 	{
1886 		mSelected = -1;
1887 	}
1888 	else
1889 	{
1890 		if (selected < 0)
1891 		{
1892 			mSelected = -1;
1893 		}
1894 		else if (selected >= mListModel->getNumberOfElements())
1895 		{
1896 			mSelected = mListModel->getNumberOfElements() - 1;
1897 		}
1898 		else
1899 		{
1900 			mSelected = selected;
1901 		}
1902 
1903 		Widget *par = getParent();
1904 		if (par == nullptr)
1905 		{
1906 			return;
1907 		}
1908 
1909 		gcn::ScrollArea* scrollArea = dynamic_cast<gcn::ScrollArea *>(par);
1910 		if (scrollArea != nullptr)
1911 		{
1912 			gcn::Rectangle scroll;
1913 			scroll.y = (itemImage ? std::max<int>(getFont()->getHeight(), itemImage->getHeight()) : getFont()->getHeight()) * mSelected;
1914 			scroll.height = (itemImage ? std::max<int>(getFont()->getHeight(), itemImage->getHeight()) : getFont()->getHeight());
1915 			scrollArea->scrollToRectangle(scroll);
1916 		}
1917 	}
1918 }
1919 
setListModel(gcn::ListModel * listModel)1920 void ImageListBox::setListModel(gcn::ListModel *listModel)
1921 {
1922 	mSelected = -1;
1923 	mListModel = listModel;
1924 	adjustSize();
1925 }
1926 
1927 
1928 /*----------------------------------------------------------------------------
1929 --  ListBoxWidget
1930 ----------------------------------------------------------------------------*/
1931 
1932 
1933 /**
1934 **  ListBoxWidget constructor.
1935 **
1936 **  @todo  Size should be parametrable, maybe remove default constructor?
1937 */
ListBoxWidget(unsigned int width,unsigned int height)1938 ListBoxWidget::ListBoxWidget(unsigned int width, unsigned int height)
1939 {
1940 	setDimension(gcn::Rectangle(0, 0, width, height));
1941 	setContent(&listbox);
1942 	setBackgroundColor(gcn::Color(128, 128, 128));
1943 }
1944 
1945 /**
1946 **  ImageListBoxWidget constructor.
1947 **
1948 **  @todo  Size should be parametrable, maybe remove default constructor?
1949 */
ImageListBoxWidget(unsigned int width,unsigned int height)1950 ImageListBoxWidget::ImageListBoxWidget(unsigned int width, unsigned int height) : ListBoxWidget(width, height),
1951 	upButtonImage(nullptr), downButtonImage(nullptr), leftButtonImage(nullptr), rightButtonImage(nullptr), hBarButtonImage(nullptr),
1952 	vBarButtonImage(nullptr),	markerImage(nullptr)
1953 {
1954 	setDimension(gcn::Rectangle(0, 0, width, height));
1955 	setContent(&listbox);
1956 }
1957 
1958 
1959 /**
1960 **  Set the list
1961 */
setList(lua_State * lua,lua_Object * lo)1962 void ListBoxWidget::setList(lua_State *lua, lua_Object *lo)
1963 {
1964 	lualistmodel.setList(lua, lo);
1965 	listbox.setListModel(&lualistmodel);
1966 	adjustSize();
1967 }
1968 
1969 /**
1970 **  Set the list
1971 */
setList(lua_State * lua,lua_Object * lo)1972 void ImageListBoxWidget::setList(lua_State *lua, lua_Object *lo)
1973 {
1974 	lualistmodel.setList(lua, lo);
1975 	listbox.setListModel(&lualistmodel);
1976 	adjustSize();
1977 }
1978 
1979 /**
1980 **  Sets the ListModel index of the selected element.
1981 **
1982 **  @param selected  The ListModel index of the selected element.
1983 **
1984 **  @see gcn::ListBox
1985 */
setSelected(int selected)1986 void ListBoxWidget::setSelected(int selected)
1987 {
1988 	listbox.setSelected(selected);
1989 }
1990 
1991 /**
1992 **  Sets the ListModel index of the selected element.
1993 **
1994 **  @param selected  The ListModel index of the selected element.
1995 **
1996 **  @see gcn::ListBox
1997 */
setSelected(int selected)1998 void ImageListBoxWidget::setSelected(int selected)
1999 {
2000 	listbox.setSelected(selected);
2001 }
2002 
2003 /**
2004 **  Gets the ListModel index of the selected element.
2005 **
2006 **  @return  The ListModel index of the selected element.
2007 **
2008 **  @see gcn::ListBox
2009 */
getSelected() const2010 int ListBoxWidget::getSelected() const
2011 {
2012 	return const_cast<gcn::ListBox &>(listbox).getSelected();
2013 }
2014 
2015 /**
2016 **  Gets the ListModel index of the selected element.
2017 **
2018 **  @return  The ListModel index of the selected element.
2019 **
2020 **  @see gcn::ListBox
2021 */
getSelected() const2022 int ImageListBoxWidget::getSelected() const
2023 {
2024 	return const_cast<ImageListBox &>(listbox).getSelected();
2025 }
2026 
2027 /**
2028 **  Set background color of the ListBoxWidget.
2029 **
2030 **  @param color  Color to set.
2031 */
setBackgroundColor(const gcn::Color & color)2032 void ListBoxWidget::setBackgroundColor(const gcn::Color &color)
2033 {
2034 	ScrollArea::setBackgroundColor(color);
2035 	ScrollArea::setBaseColor(color);
2036 	listbox.setBackgroundColor(color);
2037 }
2038 
2039 /**
2040 **  Set background color of the ListBoxWidget.
2041 **
2042 **  @param color  Color to set.
2043 */
setBackgroundColor(const gcn::Color & color)2044 void ImageListBoxWidget::setBackgroundColor(const gcn::Color &color)
2045 {
2046 	ScrollArea::setBackgroundColor(color);
2047 	ScrollArea::setBaseColor(color);
2048 	listbox.setBackgroundColor(color);
2049 }
2050 
2051 /**
2052 **  Set font of the ListBox.
2053 **
2054 **  @param font  Font to set.
2055 */
setFont(gcn::Font * font)2056 void ListBoxWidget::setFont(gcn::Font *font)
2057 {
2058 	listbox.setFont(font);
2059 	listbox.setWidth(getWidth());
2060 	adjustSize();
2061 }
2062 
2063 /**
2064 **  Set font of the ListBox.
2065 **
2066 **  @param font  Font to set.
2067 */
setFont(gcn::Font * font)2068 void ImageListBoxWidget::setFont(gcn::Font *font)
2069 {
2070 	listbox.setFont(font);
2071 	listbox.setWidth(getWidth());
2072 	adjustSize();
2073 }
2074 
2075 /**
2076 **  Adjust size of the listBox.
2077 **
2078 **  @todo Fix width of the scroll area (depend of v-scroll or not).
2079 */
adjustSize()2080 void ListBoxWidget::adjustSize()
2081 {
2082 	int i;
2083 	int width;
2084 	gcn::ListModel *listmodel;
2085 
2086 	width = listbox.getWidth();
2087 	Assert(listbox.getListModel());
2088 	listmodel = listbox.getListModel();
2089 	for (i = 0; i < listmodel->getNumberOfElements(); ++i) {
2090 		if (width < listbox.getFont()->getWidth(listmodel->getElementAt(i))) {
2091 			width = listbox.getFont()->getWidth(listmodel->getElementAt(i));
2092 		}
2093 	}
2094 	if (width != listbox.getWidth()) {
2095 		listbox.setWidth(width);
2096 	}
2097 }
2098 
2099 /**
2100 **  Adjust size of the listBox.
2101 **
2102 **  @todo Fix width of the scroll area (depend of v-scroll or not).
2103 */
adjustSize()2104 void ImageListBoxWidget::adjustSize()
2105 {
2106 	int i;
2107 	int width;
2108 	gcn::ListModel *listmodel;
2109 
2110 	width = listbox.getWidth();
2111 	Assert(listbox.getListModel());
2112 	listmodel = listbox.getListModel();
2113 	for (i = 0; i < listmodel->getNumberOfElements(); ++i) {
2114 		if (width < listbox.getFont()->getWidth(listmodel->getElementAt(i))) {
2115 			width = listbox.getFont()->getWidth(listmodel->getElementAt(i));
2116 		}
2117 	}
2118 	if (width != listbox.getWidth()) {
2119 		listbox.setWidth(width);
2120 	}
2121 }
2122 
2123 /**
2124 **  Add an action listener
2125 */
addActionListener(gcn::ActionListener * actionListener)2126 void ListBoxWidget::addActionListener(gcn::ActionListener *actionListener)
2127 {
2128 	listbox.addActionListener(actionListener);
2129 }
2130 
2131 /**
2132 **  Add an action listener
2133 */
addActionListener(gcn::ActionListener * actionListener)2134 void ImageListBoxWidget::addActionListener(gcn::ActionListener *actionListener)
2135 {
2136 	listbox.addActionListener(actionListener);
2137 }
2138 
2139 
2140 
2141 /**
2142 **  Draw the list box
2143 **
2144 **  @param  graphics Graphics to use
2145 */
draw(gcn::Graphics * graphics)2146 void ImageListBoxWidget::draw(gcn::Graphics *graphics)
2147 {
2148 	CGraphic *img = nullptr;
2149 
2150 	// Check if we have all required graphics
2151 	if (!this->upButtonImage || !this->downButtonImage || !this->leftButtonImage || !this->rightButtonImage
2152 		|| !this->upPressedButtonImage || !this->downPressedButtonImage || !this->leftPressedButtonImage || !this->rightPressedButtonImage
2153 		|| !this->markerImage || !this->hBarButtonImage || !this->vBarButtonImage) {
2154 			fprintf(stderr, "Not all graphics for ImageListBoxWidget were set\n");
2155 			ExitFatal(1);
2156 	}
2157 
2158 	gcn::Rectangle rect = getContentDimension();
2159 	img = itemImage;
2160 	img->Resize(rect.width, img->getHeight());
2161 	int y = 0;
2162 	while (y + img->getHeight() <= rect.height) {
2163 		graphics->drawImage(img, 0, 0, 0, y, getWidth(), img->getHeight());
2164 		y += img->getHeight();
2165 	}
2166 	img->SetOriginalSize();
2167 
2168 	if (mVBarVisible)
2169 	{
2170 		if (mUpButtonPressed) {
2171 			this->drawUpPressedButton(graphics);
2172 		} else {
2173 			this->drawUpButton(graphics);
2174 		}
2175 		if (mDownButtonPressed) {
2176 			this->drawDownPressedButton(graphics);
2177 		} else {
2178 			this->drawDownButton(graphics);
2179 		}
2180 		this->drawVBar(graphics);
2181 		this->drawVMarker(graphics);
2182 	}
2183 	if (mHBarVisible)
2184 	{
2185 		if (mLeftButtonPressed) {
2186 			this->drawLeftPressedButton(graphics);
2187 		} else {
2188 			this->drawLeftButton(graphics);
2189 		}
2190 		if (mRightButtonPressed) {
2191 			this->drawRightPressedButton(graphics);
2192 		} else {
2193 			this->drawRightButton(graphics);
2194 		}
2195 		this->drawHBar(graphics);
2196 		this->drawHMarker(graphics);
2197 	}
2198 	if (mContent)
2199 	{
2200 		gcn::Rectangle contdim = mContent->getDimension();
2201 		graphics->pushClipArea(getContentDimension());
2202 
2203 		if (mContent->getBorderSize() > 0)
2204 		{
2205 			img = this->itemImage;
2206 			gcn::Rectangle rec = mContent->getDimension();
2207 			rec.x -= mContent->getBorderSize();
2208 			rec.y -= mContent->getBorderSize();
2209 			rec.width += 2 * mContent->getBorderSize();
2210 			rec.height += 2 * mContent->getBorderSize();
2211 			graphics->pushClipArea(rec);
2212 			mContent->drawBorder(graphics);
2213 			graphics->popClipArea();
2214 		}
2215 
2216 		graphics->pushClipArea(contdim);
2217 		mContent->draw(graphics);
2218 		graphics->popClipArea();
2219 		graphics->popClipArea();
2220 	}
2221 }
2222 
2223 /**
2224 **  Draw the list box border
2225 **
2226 **  @param  graphics Graphics to use
2227 */
drawBorder(gcn::Graphics * graphics)2228 void ImageListBoxWidget::drawBorder(gcn::Graphics *graphics)
2229 {
2230 	gcn::Color faceColor = getBaseColor();
2231 	gcn::Color highlightColor, shadowColor;
2232 	int alpha = getBaseColor().a;
2233 	int width = getWidth() + getBorderSize() * 2 - 1;
2234 	int height = getHeight() + getBorderSize() * 2 - 1;
2235 	highlightColor = faceColor + 0x303030;
2236 	highlightColor.a = alpha;
2237 	shadowColor = faceColor - 0x303030;
2238 	shadowColor.a = alpha;
2239 
2240 	unsigned int i;
2241 	for (i = 0; i < getBorderSize(); ++i)
2242 	{
2243 		graphics->setColor(shadowColor);
2244 		graphics->drawLine(i,i, width - i, i);
2245 		graphics->drawLine(i,i + 1, i, height - i - 1);
2246 		graphics->setColor(highlightColor);
2247 		graphics->drawLine(width - i,i + 1, width - i, height - i);
2248 		graphics->drawLine(i,height - i, width - i - 1, height - i);
2249 	}
2250 }
2251 
drawUpButton(gcn::Graphics * graphics)2252 void ImageListBoxWidget::drawUpButton(gcn::Graphics* graphics)
2253 {
2254 	gcn::Rectangle dim = getUpButtonDimension();
2255 	graphics->pushClipArea(dim);
2256 
2257 	CGraphic *img = nullptr;
2258 
2259 	img = upButtonImage;
2260 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2261 	graphics->popClipArea();
2262 }
2263 
drawDownButton(gcn::Graphics * graphics)2264 void ImageListBoxWidget::drawDownButton(gcn::Graphics* graphics)
2265 {
2266 	gcn::Rectangle dim = getDownButtonDimension();
2267 	graphics->pushClipArea(dim);
2268 
2269 	CGraphic *img = nullptr;
2270 
2271 	img = downButtonImage;
2272 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2273 	graphics->popClipArea();
2274 }
2275 
drawLeftButton(gcn::Graphics * graphics)2276 void ImageListBoxWidget::drawLeftButton(gcn::Graphics* graphics)
2277 {
2278 	gcn::Rectangle dim = getLeftButtonDimension();
2279 	graphics->pushClipArea(dim);
2280 
2281 	CGraphic *img = nullptr;
2282 
2283 	img = leftButtonImage;
2284 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2285 	graphics->popClipArea();
2286 }
2287 
drawRightButton(gcn::Graphics * graphics)2288 void ImageListBoxWidget::drawRightButton(gcn::Graphics* graphics)
2289 {
2290 	gcn::Rectangle dim = getRightButtonDimension();
2291 	graphics->pushClipArea(dim);
2292 
2293 	CGraphic *img = nullptr;
2294 
2295 	img = rightButtonImage;
2296 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2297 	graphics->popClipArea();
2298 }
2299 
drawUpPressedButton(gcn::Graphics * graphics)2300 void ImageListBoxWidget::drawUpPressedButton(gcn::Graphics* graphics)
2301 {
2302 	gcn::Rectangle dim = getUpButtonDimension();
2303 	graphics->pushClipArea(dim);
2304 
2305 	CGraphic *img = nullptr;
2306 
2307 	img = upPressedButtonImage;
2308 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2309 	graphics->popClipArea();
2310 }
2311 
drawDownPressedButton(gcn::Graphics * graphics)2312 void ImageListBoxWidget::drawDownPressedButton(gcn::Graphics* graphics)
2313 {
2314 	gcn::Rectangle dim = getDownButtonDimension();
2315 	graphics->pushClipArea(dim);
2316 
2317 	CGraphic *img = nullptr;
2318 
2319 	img = downPressedButtonImage;
2320 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2321 	graphics->popClipArea();
2322 }
2323 
drawLeftPressedButton(gcn::Graphics * graphics)2324 void ImageListBoxWidget::drawLeftPressedButton(gcn::Graphics* graphics)
2325 {
2326 	gcn::Rectangle dim = getLeftButtonDimension();
2327 	graphics->pushClipArea(dim);
2328 
2329 	CGraphic *img = nullptr;
2330 
2331 	img = leftPressedButtonImage;
2332 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2333 	graphics->popClipArea();
2334 }
2335 
drawRightPressedButton(gcn::Graphics * graphics)2336 void ImageListBoxWidget::drawRightPressedButton(gcn::Graphics* graphics)
2337 {
2338 	gcn::Rectangle dim = getRightButtonDimension();
2339 	graphics->pushClipArea(dim);
2340 
2341 	CGraphic *img = nullptr;
2342 
2343 	img = rightPressedButtonImage;
2344 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2345 	graphics->popClipArea();
2346 }
2347 
drawHBar(gcn::Graphics * graphics)2348 void ImageListBoxWidget::drawHBar(gcn::Graphics *graphics)
2349 {
2350 	gcn::Rectangle dim = getHorizontalBarDimension();
2351 	graphics->pushClipArea(dim);
2352 
2353 	CGraphic *img = nullptr;
2354 
2355 	img = hBarButtonImage;
2356 	img->Resize(dim.width, dim.height);
2357 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2358 	img->SetOriginalSize();
2359 
2360 	graphics->popClipArea();
2361 }
2362 
drawVBar(gcn::Graphics * graphics)2363 void ImageListBoxWidget::drawVBar(gcn::Graphics *graphics)
2364 {
2365 	gcn::Rectangle dim = getVerticalBarDimension();
2366 	graphics->pushClipArea(dim);
2367 
2368 	CGraphic *img = nullptr;
2369 
2370 	img = vBarButtonImage;
2371 	img->Resize(dim.width, dim.height);
2372 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2373 	img->SetOriginalSize();
2374 
2375 	graphics->popClipArea();
2376 }
2377 
drawHMarker(gcn::Graphics * graphics)2378 void ImageListBoxWidget::drawHMarker(gcn::Graphics *graphics)
2379 {
2380 	gcn::Rectangle dim = getHorizontalMarkerDimension();
2381 	graphics->pushClipArea(dim);
2382 
2383 	CGraphic *img = nullptr;
2384 
2385 	img = markerImage;
2386 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2387 
2388 	graphics->popClipArea();
2389 }
2390 
drawVMarker(gcn::Graphics * graphics)2391 void ImageListBoxWidget::drawVMarker(gcn::Graphics *graphics)
2392 {
2393 	gcn::Rectangle dim = getVerticalMarkerDimension();
2394 	graphics->pushClipArea(dim);
2395 
2396 	CGraphic *img = nullptr;
2397 
2398 	img = markerImage;
2399 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2400 
2401 	graphics->popClipArea();
2402 }
2403 
getVerticalMarkerDimension()2404 gcn::Rectangle ImageListBoxWidget::getVerticalMarkerDimension()
2405 {
2406 	if (!mVBarVisible)
2407 	{
2408 		return gcn::Rectangle(0, 0, 0, 0);
2409 	}
2410 
2411 	int length, pos;
2412 	gcn::Rectangle barDim = getVerticalBarDimension();
2413 
2414 	if (mContent && mContent->getHeight() != 0)
2415 	{
2416 		length = this->markerImage->getHeight();
2417 	}
2418 	else
2419 	{
2420 		length = barDim.height;
2421 	}
2422 
2423 	if (length < mScrollbarWidth)
2424 	{
2425 		length = mScrollbarWidth;
2426 	}
2427 
2428 	if (length > barDim.height)
2429 	{
2430 		length = barDim.height;
2431 	}
2432 
2433 	if (getVerticalMaxScroll() != 0)
2434 	{
2435 		pos = ((barDim.height - length) * getVerticalScrollAmount())
2436 			/ getVerticalMaxScroll();
2437 	}
2438 	else
2439 	{
2440 		pos = 0;
2441 	}
2442 
2443 	return gcn::Rectangle(barDim.x, barDim.y + pos, mScrollbarWidth, length);
2444 }
2445 
getHorizontalMarkerDimension()2446 gcn::Rectangle ImageListBoxWidget::getHorizontalMarkerDimension()
2447 {
2448 	if (!mHBarVisible)
2449 	{
2450 		return gcn::Rectangle(0, 0, 0, 0);
2451 	}
2452 
2453 	int length, pos;
2454 	gcn::Rectangle barDim = getHorizontalBarDimension();
2455 
2456 	if (mContent && mContent->getWidth() != 0)
2457 	{
2458 		length = this->markerImage->getHeight();
2459 	}
2460 	else
2461 	{
2462 		length = barDim.width;
2463 	}
2464 
2465 	if (length < mScrollbarWidth)
2466 	{
2467 		length = mScrollbarWidth;
2468 	}
2469 
2470 	if (length > barDim.width)
2471 	{
2472 		length = barDim.width;
2473 	}
2474 
2475 	if (getHorizontalMaxScroll() != 0)
2476 	{
2477 		pos = ((barDim.width - length) * getHorizontalScrollAmount())
2478 			/ getHorizontalMaxScroll();
2479 	}
2480 	else
2481 	{
2482 		pos = 0;
2483 	}
2484 
2485 	return gcn::Rectangle(barDim.x + pos, barDim.y, length, mScrollbarWidth);
2486 }
2487 
2488 
2489 /*----------------------------------------------------------------------------
2490 --  DropDownWidget
2491 ----------------------------------------------------------------------------*/
2492 
2493 
2494 /**
2495 **  Set the list
2496 */
setList(lua_State * lua,lua_Object * lo)2497 void DropDownWidget::setList(lua_State *lua, lua_Object *lo)
2498 {
2499 	listmodel.setList(lua, lo);
2500 	setListModel(&listmodel);
2501 }
2502 
2503 /**
2504 **  Set the drop down size
2505 */
setSize(int width,int height)2506 void DropDownWidget::setSize(int width, int height)
2507 {
2508 	DropDown::setSize(width, height);
2509 	this->getListBox()->setSize(width, height);
2510 }
2511 
2512 /*----------------------------------------------------------------------------
2513 --  ImageDropDownWidget
2514 ----------------------------------------------------------------------------*/
2515 
2516 /**
2517 **  Set the list
2518 */
2519 
setListModel(LuaListModel * listModel)2520 void ImageDropDownWidget::setListModel(LuaListModel *listModel)
2521 {
2522 	Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2523 
2524 	mListBox.setListModel(listModel);
2525 
2526 	if (mListBox.getSelected() < 0)
2527 	{
2528 		mListBox.setSelected(0);
2529 	}
2530 
2531 	adjustHeight();
2532 }
2533 
setList(lua_State * lua,lua_Object * lo)2534 void ImageDropDownWidget::setList(lua_State *lua, lua_Object *lo)
2535 {
2536 	listmodel.setList(lua, lo);
2537 	setListModel(&listmodel);
2538 }
2539 
2540 /**
2541 **  Set the drop down size
2542 */
setSize(int width,int height)2543 void ImageDropDownWidget::setSize(int width, int height)
2544 {
2545 	DropDown::setSize(width, height);
2546 	this->getListBox()->setSize(width, height);
2547 }
2548 
draw(gcn::Graphics * graphics)2549 void ImageDropDownWidget::draw(gcn::Graphics *graphics)
2550 {
2551 	Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2552 	int h;
2553 
2554 	if (mDroppedDown)
2555 	{
2556 		h = mOldH;
2557 	}
2558 	else
2559 	{
2560 		h = getHeight();
2561 	}
2562 
2563 	CGraphic *img = this->itemImage;
2564 	if (!this->itemImage || !this->DownNormalImage || !this->DownPressedImage) {
2565 		fprintf(stderr, "Not all graphics for ImageDropDownWidget were set\n");
2566 		ExitFatal(1);
2567 	}
2568 
2569 	int alpha = getBaseColor().a;
2570 	gcn::Color faceColor = getBaseColor();
2571 	faceColor.a = alpha;
2572 	gcn::Color highlightColor = faceColor + 0x303030;
2573 	highlightColor.a = alpha;
2574 	gcn::Color shadowColor = faceColor - 0x303030;
2575 	shadowColor.a = alpha;
2576 
2577 
2578 	//Wyrmgus start
2579 //	img->Resize(getWidth(), h);
2580 //	graphics->drawImage(img, 0, 0, 0, 0, getWidth(), h);
2581 //	img->SetOriginalSize();
2582 	graphics->drawImage(img, 0, 0, 0, 0, img->getWidth(), img->getHeight());
2583 	//Wyrmgus end
2584 
2585 	graphics->setFont(getFont());
2586 
2587 	if (mListBox.getListModel() && mListBox.getSelected() >= 0)
2588 	{
2589 		graphics->drawText(mListBox.getListModel()->getElementAt(mListBox.getSelected()),
2590 			2, (h - getFont()->getHeight()) / 2);
2591 	}
2592 
2593 	//Wyrmgus start
2594 	/*
2595 	if (hasFocus())
2596 	{
2597 		graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth() - h, h));
2598 	}
2599 	*/
2600 	//Wyrmgus end
2601 
2602 	drawButton(graphics);
2603 
2604 	if (mDroppedDown)
2605 	{
2606 		graphics->pushClipArea(mScrollArea->getDimension());
2607 		mScrollArea->draw(graphics);
2608 		graphics->popClipArea();
2609 
2610 		// Draw two lines separating the ListBox with se selected
2611 		// element view.
2612 		//Wyrmgus start
2613 		/*
2614 		graphics->setColor(highlightColor);
2615 		graphics->drawLine(0, h, getWidth(), h);
2616 		graphics->setColor(shadowColor);
2617 		graphics->drawLine(0, h + 1,getWidth(),h + 1);
2618 		*/
2619 		//Wyrmgus end
2620 	}
2621 }
2622 
drawBorder(gcn::Graphics * graphics)2623 void ImageDropDownWidget::drawBorder(gcn::Graphics *graphics)
2624 {
2625 	gcn::Color faceColor = getBaseColor();
2626 	gcn::Color highlightColor, shadowColor;
2627 	int alpha = getBaseColor().a;
2628 	int width = getWidth() + getBorderSize() * 2 - 1;
2629 	int height = getHeight() + getBorderSize() * 2 - 1;
2630 	highlightColor = faceColor + 0x303030;
2631 	highlightColor.a = alpha;
2632 	shadowColor = faceColor - 0x303030;
2633 	shadowColor.a = alpha;
2634 
2635 	unsigned int i;
2636 	for (i = 0; i < getBorderSize(); ++i)
2637 	{
2638 		graphics->setColor(shadowColor);
2639 		graphics->drawLine(i,i, width - i, i);
2640 		graphics->drawLine(i,i + 1, i, height - i - 1);
2641 		graphics->setColor(highlightColor);
2642 		graphics->drawLine(width - i,i + 1, width - i, height - i);
2643 		graphics->drawLine(i,height - i, width - i - 1, height - i);
2644 	}
2645 }
2646 
drawButton(gcn::Graphics * graphics)2647 void ImageDropDownWidget::drawButton(gcn::Graphics *graphics)
2648 {
2649 	int h;
2650 	if (mDroppedDown)
2651 	{
2652 		h = mOldH;
2653 	}
2654 	else
2655 	{
2656 		h = getHeight();
2657 	}
2658 	//Wyrmgus start
2659 //	int x = getWidth() - h;
2660 	int x = getWidth() - (h - 1);
2661 	//Wyrmgus end
2662 	int y = 0;
2663 
2664 	CGraphic *img = nullptr;
2665 	if (mDroppedDown) {
2666 		img = this->DownPressedImage;
2667 	} else {
2668 		img = this->DownNormalImage;
2669 	}
2670 	//Wyrmgus start
2671 //	img->Resize(h, h);
2672 	//Wyrmgus end
2673 	graphics->drawImage(img, 0, 0, x, y, h, h);
2674 	//Wyrmgus start
2675 //	img->SetOriginalSize();
2676 	//Wyrmgus end
2677 }
2678 
getSelected()2679 int ImageDropDownWidget::getSelected()
2680 {
2681 	Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2682 
2683 	return mListBox.getSelected();
2684 }
2685 
setSelected(int selected)2686 void ImageDropDownWidget::setSelected(int selected)
2687 {
2688 	Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2689 
2690 	if (selected >= 0)
2691 	{
2692 		mListBox.setSelected(selected);
2693 	}
2694 }
2695 
adjustHeight()2696 void ImageDropDownWidget::adjustHeight()
2697 {
2698 	Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2699 
2700 	int listBoxHeight = mListBox.getHeight();
2701 	int h2 = mOldH ? mOldH : getFont()->getHeight();
2702 
2703 	setHeight(h2);
2704 
2705 	// The addition/subtraction of 2 compensates for the seperation lines
2706 	// seperating the selected element view and the scroll area.
2707 
2708 	if (mDroppedDown && getParent())
2709 	{
2710 		int h = getParent()->getHeight() - getY();
2711 
2712 		if (listBoxHeight > h - h2 - 2)
2713 		{
2714 			mScrollArea->setHeight(h - h2 - 2);
2715 			setHeight(h);
2716 		}
2717 		else
2718 		{
2719 			setHeight(listBoxHeight + h2 + 2);
2720 			mScrollArea->setHeight(listBoxHeight);
2721 		}
2722 	}
2723 
2724 	mScrollArea->setWidth(getWidth());
2725 	mScrollArea->setPosition(0, h2 + 2);
2726 }
2727 
setListBox(ImageListBox * listBox)2728 void ImageDropDownWidget::setListBox(ImageListBox *listBox)
2729 {
2730 	listBox->setSelected(mListBox.getSelected());
2731 	listBox->setListModel(mListBox.getListModel());
2732 	listBox->addActionListener(this);
2733 
2734 	if (mScrollArea->getContent() != nullptr)
2735 	{
2736 		mListBox.removeActionListener(this);
2737 	}
2738 
2739 	mListBox = *listBox;
2740 
2741 	mScrollArea->setContent(&mListBox);
2742 
2743 	if (mListBox.getSelected() < 0)
2744 	{
2745 		mListBox.setSelected(0);
2746 	}
2747 }
2748 
setFont(gcn::Font * font)2749 void ImageDropDownWidget::setFont(gcn::Font *font)
2750 {
2751 	gcn::Widget::setFont(font);
2752 	mListBox.setFont(font);
2753 }
2754 
_mouseInputMessage(const gcn::MouseInput & mouseInput)2755 void ImageDropDownWidget::_mouseInputMessage(const gcn::MouseInput &mouseInput)
2756 {
2757 	gcn::BasicContainer::_mouseInputMessage(mouseInput);
2758 
2759 	if (mDroppedDown)
2760 	{
2761 		Assert(mScrollArea && mScrollArea->getContent() != nullptr);
2762 
2763 		if (mouseInput.y >= mOldH)
2764 		{
2765 			gcn::MouseInput mi = mouseInput;
2766 			mi.y -= mScrollArea->getY();
2767 			mScrollArea->_mouseInputMessage(mi);
2768 
2769 			if (mListBox.hasFocus())
2770 			{
2771 				mi.y -= mListBox.getY();
2772 				mListBox._mouseInputMessage(mi);
2773 			}
2774 		}
2775 	}
2776 }
2777 
2778 /**
2779 **  StatBoxWidget constructor
2780 **
2781 **  @param width   Width of the StatBoxWidget.
2782 **  @param height  Height of the StatBoxWidget.
2783 */
StatBoxWidget(int width,int height)2784 StatBoxWidget::StatBoxWidget(int width, int height) : percent(100)
2785 {
2786 	setWidth(width);
2787 	setHeight(height);
2788 
2789 	setBackgroundColor(gcn::Color(0, 0, 0));
2790 	setBaseColor(gcn::Color(255, 255, 255));
2791 	setForegroundColor(gcn::Color(128, 128, 128));
2792 }
2793 
2794 /**
2795 **  Draw StatBoxWidget.
2796 **
2797 **  @param graphics  Graphic driver used to draw.
2798 **
2799 **  @todo caption seem to be placed upper than the middle.
2800 **  @todo set direction (hor./vert.) and growing direction(up/down, left/rigth).
2801 */
draw(gcn::Graphics * graphics)2802 void StatBoxWidget::draw(gcn::Graphics *graphics)
2803 {
2804 	int width;
2805 	int height;
2806 
2807 	width = getWidth();
2808 	height = getHeight();
2809 
2810 	graphics->setColor(getBackgroundColor());
2811 	graphics->fillRectangle(gcn::Rectangle(0, 0, width, height));
2812 
2813 	graphics->setColor(getBaseColor());
2814 	graphics->drawRectangle(gcn::Rectangle(1, 1, width - 2, height - 2));
2815 
2816 	graphics->setColor(getForegroundColor());
2817 	width = percent * width / 100;
2818 	graphics->fillRectangle(gcn::Rectangle(2, 2, width - 4, height - 4));
2819 	graphics->setFont(getFont());
2820 	graphics->drawText(getCaption(),
2821 					   (getWidth() - getFont()->getWidth(getCaption())) / 2,
2822 					   (height - getFont()->getHeight()) / 2);
2823 }
2824 
2825 /**
2826 **  Set caption of StatBoxWidget.
2827 **
2828 **  @param caption  New value.
2829 */
setCaption(const std::string & caption)2830 void StatBoxWidget::setCaption(const std::string &caption)
2831 {
2832 	this->caption = caption;
2833 	this->setDirty(true);
2834 }
2835 
2836 /**
2837 **  Get caption of StatBoxWidget.
2838 */
2839 
getCaption() const2840 const std::string &StatBoxWidget::getCaption() const
2841 {
2842 	return caption;
2843 }
2844 
2845 /**
2846 **  Set percent of StatBoxWidget.
2847 **
2848 **  @param percent  New value.
2849 */
setPercent(const int percent)2850 void StatBoxWidget::setPercent(const int percent)
2851 {
2852 	this->setDirty(true);
2853 	this->percent = percent;
2854 }
2855 
2856 /**
2857 **  Get percent of StatBoxWidget.
2858 */
getPercent() const2859 int StatBoxWidget::getPercent() const
2860 {
2861 	return percent;
2862 }
2863 
2864 
2865 /*----------------------------------------------------------------------------
2866 --  MenuScreen
2867 ----------------------------------------------------------------------------*/
2868 
2869 
2870 /**
2871 **  MenuScreen constructor
2872 */
MenuScreen()2873 MenuScreen::MenuScreen() :
2874 	Container(), runLoop(true), logiclistener(0), drawUnder(false), running(false)
2875 {
2876 	setDimension(gcn::Rectangle(0, 0, Video.Width, Video.Height));
2877 	setOpaque(false);
2878 
2879 	// The gui must be set immediately as it is used by widgets
2880 	// when they are added to the container
2881 	oldtop = Gui->getTop();
2882 	Gui->setTop(this);
2883 }
2884 
2885 /**
2886 **  Run the menu.  Loops until stop is called.
2887 */
run(bool loop)2888 int MenuScreen::run(bool loop)
2889 {
2890 	loopResult = 0;
2891 	runLoop = loop;
2892 	running = true;
2893 
2894 	CursorState = CursorStatePoint;
2895 	GameCursor = UI.Point.Cursor;
2896 	CursorOn = CursorOnUnknown;
2897 
2898 	CallbackMusicOn();
2899 
2900 	if (loop) {
2901 		const EventCallback *old_callbacks = GetCallbacks();
2902 		SetCallbacks(&GuichanCallbacks);
2903 		while (runLoop) {
2904 			UpdateDisplay();
2905 			RealizeVideoMemory();
2906 			CheckMusicFinished();
2907 			WaitEventsOneFrame();
2908 		}
2909 		SetCallbacks(old_callbacks);
2910 		Gui->setTop(this->oldtop);
2911 	} else {
2912 		SetCallbacks(&GuichanCallbacks);
2913 		MenuStack.push(this);
2914 	}
2915 
2916 	return this->loopResult;
2917 }
2918 
2919 /**
2920 **  Stop the menu from running
2921 */
stop(int result,bool stopAll)2922 void MenuScreen::stop(int result, bool stopAll)
2923 {
2924 	if (running == false)
2925 		return;
2926 
2927 	if (!this->runLoop) {
2928 		Gui->setTop(this->oldtop);
2929 		Assert(MenuStack.top() == this);
2930 		MenuStack.pop();
2931 		if (stopAll) {
2932 			while (!MenuStack.empty()) {
2933 				MenuStack.pop();
2934 			}
2935 		}
2936 		if (MenuStack.empty()) {
2937 			//InterfaceState = IfaceStateNormal;
2938 			if (!Editor.Running) {
2939 				SetCallbacks(&GameCallbacks);
2940 			} else {
2941 				SetCallbacks(&EditorCallbacks);
2942 			}
2943 			GamePaused = false;
2944 			UI.StatusLine.Clear();
2945 			if (GameRunning) {
2946 				UIHandleMouseMove(CursorScreenPos);
2947 			}
2948 		}
2949 	}
2950 
2951 	runLoop = false;
2952 	loopResult = result;
2953 	running = false;
2954 }
2955 
addLogicCallback(LuaActionListener * listener)2956 void MenuScreen::addLogicCallback(LuaActionListener *listener)
2957 {
2958 	logiclistener = listener;
2959 }
2960 
draw(gcn::Graphics * graphics)2961 void MenuScreen::draw(gcn::Graphics *graphics)
2962 {
2963 	if (this->drawUnder) {
2964 		gcn::Rectangle r = Gui->getGraphics()->getCurrentClipArea();
2965 		Gui->getGraphics()->popClipArea();
2966 		Gui->draw(oldtop);
2967 		Gui->getGraphics()->pushClipArea(r);
2968 	}
2969 	gcn::Container::draw(graphics);
2970 }
2971 
logic()2972 void MenuScreen::logic()
2973 {
2974 	if (NetConnectRunning == 2) {
2975 		NetworkProcessClientRequest();
2976 	}
2977 	if (NetConnectRunning == 1) {
2978 		NetworkProcessServerRequest();
2979 	}
2980 	if (logiclistener) {
2981 		logiclistener->action("");
2982 	}
2983 	Container::logic();
2984 }
2985 
2986 //@}
2987