1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "components.h"
13 
14 #include <algorithm>
15 
16 #include "metrics.h"
17 #include "core_data.h"
18 #include "platform_util.h"
19 #include "util.h"
20 #include "conversion.h"
21 #include "lang.h"
22 #include "gen_uuid.h"
23 //#include <cxxabi.h>
24 #include "leak_dumper.h"
25 
26 using namespace std;
27 using namespace Shared::Util;
28 
29 namespace Glest{ namespace Game{
30 
31 // =====================================================
32 //	class GraphicComponent
33 // =====================================================
34 
35 float GraphicComponent::anim= 0.f;
36 float GraphicComponent::fade= 0.f;
37 const float GraphicComponent::animSpeed= 0.02f;
38 const float GraphicComponent::fadeSpeed= 0.01f;
39 // WHITE
40 Vec3f GraphicComponent::customTextColor = Vec3f(1.0,1.0,1.0);
41 
42 std::map<std::string, std::map<std::string, GraphicComponent *> > GraphicComponent::registeredGraphicComponentList;
43 
GraphicComponent(std::string containerName,std::string objName,bool registerControl)44 GraphicComponent::GraphicComponent(std::string containerName, std::string objName, bool registerControl) {
45 	this->containerName = containerName;
46 	this->instanceName = "";
47 	if(containerName == "" || objName == "") {
48 	    //char szBuf[8096]="";
49 	    //snprintf(szBuf,8096,"Control not properly registered Container [%s] Control [%s]\n",containerName.c_str(),objName.c_str());
50 		//throw megaglest_runtime_error(szBuf);
51 	}
52 	if(objName != "" && registerControl) {
53 		registerGraphicComponent(containerName,objName);
54 	}
55 	else {
56 		this->instanceName = objName;
57 	}
58 	this->fontCallbackName = objName + "_" + getNewUUD();
59 	CoreData::getInstance().registerFontChangedCallback(this->getFontCallbackName(), this);
60 
61 	enabled  = true;
62 	editable = true;
63 	visible  = true;
64 	x = 0;
65 	y = 0;
66 	w = 0;
67 	h = 0;
68 	text = "";
69 	font = NULL;
70 	font3D = NULL;
71 	textNativeTranslation = "";
72 }
73 
getNewUUD()74 string GraphicComponent::getNewUUD() {
75 	char  uuid_str[38];
76 	get_uuid_string(uuid_str,sizeof(uuid_str));
77 	return string(uuid_str);
78 }
79 
~GraphicComponent()80 GraphicComponent::~GraphicComponent() {
81 	CoreData::getInstance().unRegisterFontChangedCallback(this->getFontCallbackName());
82 }
83 
clearRegisteredComponents(std::string containerName)84 void GraphicComponent::clearRegisteredComponents(std::string containerName) {
85 	if(containerName == "") {
86 		GraphicComponent::registeredGraphicComponentList.clear();
87 	}
88 	else {
89 		GraphicComponent::registeredGraphicComponentList[containerName].clear();
90 	}
91 }
92 
clearRegisterGraphicComponent(std::string containerName,std::string objName)93 void GraphicComponent::clearRegisterGraphicComponent(std::string containerName, std::string objName) {
94 	GraphicComponent *obj = findRegisteredComponent(containerName, objName);
95 	if(obj) {
96 		GraphicComponent::registeredGraphicComponentList[containerName].erase(objName);
97 	}
98 }
99 
clearRegisterGraphicComponent(std::string containerName,std::vector<std::string> objNameList)100 void GraphicComponent::clearRegisterGraphicComponent(std::string containerName, std::vector<std::string> objNameList) {
101 	for(int idx = 0; idx < (int)objNameList.size(); ++idx) {
102 		GraphicComponent::clearRegisterGraphicComponent(containerName, objNameList[idx]);
103 	}
104 }
105 
registerGraphicComponent(std::string containerName,std::string objName)106 void GraphicComponent::registerGraphicComponent(std::string containerName, std::string objName) {
107 	// unregistered old name if we have been renamed
108 	if(this->getInstanceName() != "") {
109 		//printf("RENAME Register Callback detected calling: Control old [%s] new [%s]\n",this->getInstanceName().c_str(),objName.c_str());
110 		clearRegisterGraphicComponent(this->containerName, this->getInstanceName());
111 	}
112 	else {
113 		//printf("NEW Register Callback detected calling: Control container [%s] name [%s]\n",containerName.c_str(),objName.c_str());
114 	}
115 
116 	if(containerName == "" || objName == "") {
117 	    //char szBuf[8096]="";
118 	    //snprintf(szBuf,8096,"Control not properly registered Container [%s] Control [%s]\n",this->containerName.c_str(),objName.c_str());
119 		//throw megaglest_runtime_error(szBuf);
120 	}
121 
122 	this->containerName = containerName;
123 	this->instanceName = objName;
124 	registeredGraphicComponentList[containerName][objName] = this;
125 	//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] registered [%s] [%s] count = %d\n",__FILE__,__FUNCTION__,__LINE__,containerName.c_str(),instanceName.c_str(),registeredGraphicComponentList[containerName].size());
126 }
127 
registerGraphicComponentOnlyFontCallbacks(std::string containerName,std::string objName)128 void GraphicComponent::registerGraphicComponentOnlyFontCallbacks(std::string containerName, std::string objName) {
129 	if(this->getInstanceName() != "") {
130 		//printf("(FONT ONLY) RENAME Register Callback detected calling: Control old [%s] new [%s]\n",this->getInstanceName().c_str(),objName.c_str());
131 		clearRegisterGraphicComponent(this->containerName, this->getInstanceName());
132 	}
133 	else {
134 		//printf("(FONT ONLY) NEW Register Callback detected calling: Control container [%s] name [%s]\n",containerName.c_str(),objName.c_str());
135 	}
136 
137 	if(containerName == "" || objName == "") {
138 	    //char szBuf[8096]="";
139 	    //snprintf(szBuf,8096,"Control not properly registered Container [%s] Control [%s]\n",this->containerName.c_str(),objName.c_str());
140 		//throw megaglest_runtime_error(szBuf);
141 	}
142 
143 	this->containerName = containerName;
144 	this->instanceName = objName;
145 }
146 
findRegisteredComponent(std::string containerName,std::string objName)147 GraphicComponent * GraphicComponent::findRegisteredComponent(std::string containerName, std::string objName) {
148 	GraphicComponent *result = NULL;
149 
150 	std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
151 	if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
152 		std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.find(objName);
153 		if(iterFind2 != iterFind1->second.end()) {
154 			result = iterFind2->second;
155 		}
156 	}
157 	return result;
158 }
159 
applyAllCustomProperties(std::string containerName)160 void GraphicComponent::applyAllCustomProperties(std::string containerName) {
161 	std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
162 	if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
163 		for(std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.begin();
164 				iterFind2 != iterFind1->second.end(); ++iterFind2) {
165 			iterFind2->second->applyCustomProperties(containerName);
166 		}
167 	}
168 }
169 
applyCustomProperties(std::string containerName)170 void GraphicComponent::applyCustomProperties(std::string containerName) {
171 	if(instanceName != "") {
172 		std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
173 		if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
174 			std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.find(instanceName);
175 			if(iterFind2 != iterFind1->second.end()) {
176 				Config &config = Config::getInstance();
177 
178 				//string languageToken = config.getString("Lang");
179 				string languageToken = Lang::getInstance().getLanguage();
180 
181 				//if(dynamic_cast<GraphicButton *>(iterFind2->second) != NULL) {
182 				GraphicComponent *ctl = dynamic_cast<GraphicComponent *>(iterFind2->second);
183 
184 				// First check default overrides
185 				ctl->x = config.getInt(containerName + "_" + iterFind2->first + "_x",intToStr(ctl->x).c_str());
186 				ctl->y = config.getInt(containerName + "_" + iterFind2->first + "_y",intToStr(ctl->y).c_str());
187 				ctl->w = config.getInt(containerName + "_" + iterFind2->first + "_w",intToStr(ctl->w).c_str());
188 				ctl->h = config.getInt(containerName + "_" + iterFind2->first + "_h",intToStr(ctl->h).c_str());
189 				ctl->visible = config.getBool(containerName + "_" + iterFind2->first + "_visible",boolToStr(ctl->visible).c_str());
190 
191 				// Now check language specific overrides
192 				ctl->x = config.getInt(containerName + "_" + iterFind2->first + "_x_" + languageToken, intToStr(ctl->x).c_str());
193 				ctl->y = config.getInt(containerName + "_" + iterFind2->first + "_y_" + languageToken, intToStr(ctl->y).c_str());
194 				ctl->w = config.getInt(containerName + "_" + iterFind2->first + "_w_" + languageToken, intToStr(ctl->w).c_str());
195 				ctl->h = config.getInt(containerName + "_" + iterFind2->first + "_h_" + languageToken, intToStr(ctl->h).c_str());
196 				ctl->visible = config.getBool(containerName + "_" + iterFind2->first + "_visible_" + languageToken,boolToStr(ctl->visible).c_str());
197 			}
198 		}
199 	}
200 }
201 
saveAllCustomProperties(std::string containerName)202 bool GraphicComponent::saveAllCustomProperties(std::string containerName) {
203 	SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] registered [%s] count = %d\n",__FILE__,__FUNCTION__,__LINE__,containerName.c_str(),registeredGraphicComponentList[containerName].size());
204 
205 	bool foundPropertiesToSave = false;
206 	std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
207 	if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
208 		for(std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.begin();
209 				iterFind2 != iterFind1->second.end(); ++iterFind2) {
210 			bool saved = iterFind2->second->saveCustomProperties(containerName);
211 			foundPropertiesToSave = (saved || foundPropertiesToSave);
212 		}
213 	}
214 
215 	if(foundPropertiesToSave == true) {
216 		Config &config = Config::getInstance();
217 		config.save();
218 	}
219 
220 	return foundPropertiesToSave;
221 }
222 
saveCustomProperties(std::string containerName)223 bool GraphicComponent::saveCustomProperties(std::string containerName) {
224 	bool savedChange = false;
225 	if(instanceName != "") {
226 
227 		SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for [%s] [%s]\n",__FILE__,__FUNCTION__,__LINE__,containerName.c_str(),instanceName.c_str());
228 
229 		std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
230 		if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
231 
232 			SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for [%s]\n",__FILE__,__FUNCTION__,__LINE__,instanceName.c_str());
233 
234 			std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.find(instanceName);
235 			if(iterFind2 != iterFind1->second.end()) {
236 
237 				SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] FOUND [%s]\n",__FILE__,__FUNCTION__,__LINE__,instanceName.c_str());
238 
239 				Config &config = Config::getInstance();
240 
241 				//string languageToken = config.getString("Lang");
242 
243 				//if(dynamic_cast<GraphicButton *>(iterFind2->second) != NULL) {
244 				GraphicComponent *ctl = dynamic_cast<GraphicComponent *>(iterFind2->second);
245 
246 				// First check default overrides
247 				config.setInt(containerName + "_" + iterFind2->first + "_x",ctl->x);
248 				config.setInt(containerName + "_" + iterFind2->first + "_y",ctl->y);
249 				config.setInt(containerName + "_" + iterFind2->first + "_w",ctl->w);
250 				config.setInt(containerName + "_" + iterFind2->first + "_h",ctl->h);
251 
252 				savedChange = true;
253 				// Now check language specific overrides
254 				//ctl->x = config.getInt(containerName + "_" + iterFind2->first + "_x_" + languageToken, intToStr(ctl->x).c_str());
255 				//ctl->y = config.getInt(containerName + "_" + iterFind2->first + "_y_" + languageToken, intToStr(ctl->y).c_str());
256 				//ctl->w = config.getInt(containerName + "_" + iterFind2->first + "_w_" + languageToken, intToStr(ctl->w).c_str());
257 				//ctl->h = config.getInt(containerName + "_" + iterFind2->first + "_h_" + languageToken, intToStr(ctl->h).c_str());
258 
259 				//}
260 			}
261 		}
262 	}
263 
264 	return savedChange;
265 }
266 
setFont(Font2D * font)267 void GraphicComponent::setFont(Font2D *font) {
268 	this->font = font;
269 	if (this->font != NULL) {
270 		this->font2DUniqueId = font->getFontUniqueId();
271 	}
272 	else {
273 		this->font2DUniqueId = "";
274 	}
275 }
276 
setFont3D(Font3D * font)277 void GraphicComponent::setFont3D(Font3D *font) {
278 	this->font3D = font;
279 	if (this->font3D != NULL) {
280 		this->font3DUniqueId = font->getFontUniqueId();
281 	}
282 	else {
283 		this->font3DUniqueId = "";
284 	}
285 }
286 
FontChangedCallback(std::string fontUniqueId,Font * font)287 void GraphicComponent::FontChangedCallback(std::string fontUniqueId, Font *font) {
288 	//printf("In FontChanged for [%s] font [%p] Control 2D [%s] 3D [%s]\n", fontUniqueId.c_str(),font,this->font2DUniqueId.c_str(),this->font3DUniqueId.c_str());
289 	if (fontUniqueId != "") {
290 		if (fontUniqueId == this->font2DUniqueId) {
291 			if (font != NULL) {
292 				this->font = (Font2D *)font;
293 			}
294 			else {
295 				this->font = NULL;
296 			}
297 		}
298 		else if (fontUniqueId == this->font3DUniqueId) {
299 			if (font != NULL) {
300 				this->font3D = (Font3D *)font;
301 			}
302 			else {
303 				this->font3D = NULL;
304 			}
305 		}
306 	}
307 }
308 
reloadFonts()309 void GraphicComponent::reloadFonts() {
310 	setFont(CoreData::getInstance().getMenuFontNormal());
311 	setFont3D(CoreData::getInstance().getMenuFontNormal3D());
312 }
313 
reloadFontsForRegisterGraphicComponents(std::string containerName)314 void GraphicComponent::reloadFontsForRegisterGraphicComponents(std::string containerName) {
315 	std::map<std::string, std::map<std::string, GraphicComponent *> >::iterator iterFind1 = GraphicComponent::registeredGraphicComponentList.find(containerName);
316 	if(iterFind1 != GraphicComponent::registeredGraphicComponentList.end()) {
317 		for(std::map<std::string, GraphicComponent *>::iterator iterFind2 = iterFind1->second.begin();
318 				iterFind2 != iterFind1->second.end(); ++iterFind2) {
319 			GraphicComponent *ctl = dynamic_cast<GraphicComponent *>(iterFind2->second);
320 			if(ctl) {
321 				ctl->reloadFonts();
322 			}
323 		}
324 	}
325 }
326 
init(int x,int y,int w,int h)327 void GraphicComponent::init(int x, int y, int w, int h) {
328     this->x= x;
329     this->y= y;
330     this->w= w;
331     this->h= h;
332     reloadFonts();
333 	enabled= true;
334 }
335 
mouseMove(int x,int y)336 bool GraphicComponent::mouseMove(int x, int y) {
337 	if(this->getVisible() == false) {
338 		return false;
339 	}
340 
341     return
342         x > this->x &&
343         y > this->y &&
344         x < this->x + w &&
345         y < this->y + h;
346 }
347 
mouseClick(int x,int y)348 bool GraphicComponent::mouseClick(int x, int y){
349 	if(getVisible() && getEnabled() && getEditable())
350     	return mouseMove(x, y);
351     else
352     	return false;
353 }
354 
update()355 void GraphicComponent::update(){
356 	fade+= fadeSpeed;
357 	anim+= animSpeed;
358 	if(fade>1.f) fade= 1.f;
359 	if(anim>1.f) anim= 0.f;
360 }
361 
resetFade()362 void GraphicComponent::resetFade(){
363 	fade= 0.f;
364 }
365 
366 // =====================================================
367 //	class GraphicLabel
368 // =====================================================
369 
370 const int GraphicLabel::defH= 20;
371 const int GraphicLabel::defW= 70;
372 
GraphicLabel(std::string containerName,std::string objName,bool registerControl)373 GraphicLabel::GraphicLabel(std::string containerName, std::string objName, bool registerControl) :
374 		GraphicComponent(containerName, objName, registerControl) {
375 	centered = false;
376 	wordWrap = false;
377 	centeredW = -1;
378 	centeredH = 1;
379 	editable = false;
380 	editModeEnabled = false;
381 	maxEditWidth = -1;
382 	maxEditRenderWidth = -1;
383 	renderBackground = false;
384 	backgroundColor=Vec4f(0.2f,0.2f,0.2f,0.6f);
385 	isPassword = false;
386 	texture = NULL;
387 }
388 
init(int x,int y,int w,int h,bool centered,Vec3f textColor,bool wordWrap)389 void GraphicLabel::init(int x, int y, int w, int h, bool centered, Vec3f textColor, bool wordWrap) {
390 	GraphicComponent::init(x, y, w, h);
391 	this->centered= centered;
392 	this->textColor=textColor;
393 	this->wordWrap = wordWrap;
394 }
395 
mouseMove(int x,int y)396 bool GraphicLabel::mouseMove(int x, int y) {
397 	if(this->getVisible() == false) {
398 		return false;
399 	}
400 
401 	int useWidth = w;
402 	if(text.length() > 0 && font3D != NULL) {
403 		float lineWidth = (font3D->getTextHandler()->Advance(text.c_str()) * Shared::Graphics::Font::scaleFontValue);
404 		useWidth = (int)lineWidth;
405 	}
406 
407 	if(editable && useWidth<getMaxEditRenderWidth()){
408 		useWidth = getMaxEditRenderWidth();
409 	}
410 
411     return
412         x > this->x &&
413         y > this->y &&
414         x < this->x + useWidth &&
415         y < this->y + h;
416 }
417 
getCenteredW() const418 bool GraphicLabel::getCenteredW() const {
419 	bool result = (centered || centeredW == 1);
420 	return result;
421 }
setCenteredW(bool centered)422 void GraphicLabel::setCenteredW(bool centered) {
423 	centeredW = (centered ? 1 : 0);
424 }
425 
getCenteredH() const426 bool GraphicLabel::getCenteredH() const {
427 	bool result = (centered || centeredH == 1);
428 	return result;
429 }
setCenteredH(bool centered)430 void GraphicLabel::setCenteredH(bool centered) {
431 	centeredH = (centered ? 1 : 0);
432 }
433 
434 // =====================================================
435 //	class GraphicButton
436 // =====================================================
437 
438 const int GraphicButton::defH= 22;
439 const int GraphicButton::defW= 90;
440 
GraphicButton(std::string containerName,std::string objName,bool registerControl)441 GraphicButton::GraphicButton(std::string containerName, std::string objName, bool registerControl) :
442 	GraphicComponent(containerName,objName,registerControl) {
443 
444 	lighted = false;
445 	alwaysLighted = false;
446 	useCustomTexture = false;
447 	customTexture = NULL;
448 }
449 
init(int x,int y,int w,int h)450 void GraphicButton::init(int x, int y, int w, int h){
451 	GraphicComponent::init(x, y, w, h);
452     lighted= false;
453 }
454 
mouseMove(int x,int y)455 bool GraphicButton::mouseMove(int x, int y){
456 	if(this->getVisible() == false) {
457 		return false;
458 	}
459 
460 	bool b= GraphicComponent::mouseMove(x, y);
461     lighted= b;
462     return b;
463 }
464 
465 // =====================================================
466 //	class GraphicListBox
467 // =====================================================
468 
469 const int GraphicListBox::defH= 22;
470 const int GraphicListBox::defW= 140;
471 
GraphicListBox(std::string containerName,std::string objName)472 GraphicListBox::GraphicListBox(std::string containerName, std::string objName)
473 : GraphicComponent(containerName, objName), graphButton1(containerName, objName + "_button1"),
474 											graphButton2(containerName, objName + "_button2") {
475     selectedItemIndex = 0;
476     lighted = false;
477     leftControlled = false;
478 }
479 
init(int x,int y,int w,int h,Vec3f textColor)480 void GraphicListBox::init(int x, int y, int w, int h, Vec3f textColor){
481 	GraphicComponent::init(x, y, w, h);
482 
483 	this->textColor=textColor;
484 	graphButton1.init(x, y, 22, h);
485     graphButton2.init(x+w-22, y, 22, h);
486     graphButton1.setText("<");
487     graphButton2.setText(">");
488     selectedItemIndex=-1;
489     lighted=false;
490 }
491 
getTextNativeTranslation()492 const string & GraphicListBox::getTextNativeTranslation() {
493 	if(this->translated_items.empty() == true ||
494 			this->selectedItemIndex < 0 ||
495 			this->selectedItemIndex >= (int)this->translated_items.size() ||
496 			this->items.size() != this->translated_items.size()) {
497 		return this->text;
498 	}
499 	else {
500 		return this->translated_items[this->selectedItemIndex];
501 	}
502 }
503 
504 //queryes
pushBackItem(string item,string translated_item)505 void GraphicListBox::pushBackItem(string item, string translated_item){
506     items.push_back(item);
507     translated_items.push_back(translated_item);
508     setSelectedItemIndex(0);
509 }
510 
setItems(const vector<string> & items,const vector<string> translated_items)511 void GraphicListBox::setItems(const vector<string> &items, const vector<string> translated_items){
512     this->items= items;
513     this->translated_items = translated_items;
514     if(items.empty() == false) {
515     	setSelectedItemIndex(0);
516     }
517     else {
518     	selectedItemIndex=-1;
519     	setText("");
520     }
521 }
522 
setSelectedItemIndex(int index,bool errorOnMissing)523 void GraphicListBox::setSelectedItemIndex(int index, bool errorOnMissing){
524 	if(errorOnMissing == true && (index < 0 || index >= (int)items.size())) {
525 	    char szBuf[8096]="";
526 	    snprintf(szBuf,8096,"Index not found in listbox name: [%s] value index: %d size: %lu",this->instanceName.c_str(),index,(unsigned long)items.size());
527 		throw megaglest_runtime_error(szBuf);
528 	}
529     selectedItemIndex= index;
530     setText(getSelectedItem());
531 }
532 
setLeftControlled(bool leftControlled)533 void GraphicListBox::setLeftControlled(bool leftControlled) {
534 	if(this->leftControlled!=leftControlled){
535 		this->leftControlled= leftControlled;
536 		if(leftControlled==true) {
537 			graphButton2.setX(x+graphButton1.getW()-4);
538 			graphButton2.setH(graphButton2.getH()-4);
539 			graphButton2.setW(graphButton2.getW()-4);
540 			graphButton1.setH(graphButton1.getH()-4);
541 			graphButton1.setW(graphButton1.getW()-4);
542 			graphButton2.setY(graphButton2.getY()+2);
543 			graphButton1.setY(graphButton1.getY()+2);
544 		}
545 		else {
546 			graphButton2.setX(x+w-graphButton2.getW()+4);
547 			graphButton2.setH(graphButton2.getH()+4);
548 			graphButton2.setW(graphButton2.getW()+4);
549 			graphButton1.setH(graphButton1.getH()+4);
550 			graphButton1.setW(graphButton1.getW()+4);
551 			graphButton2.setY(graphButton2.getY()-2);
552 			graphButton1.setY(graphButton1.getY()-2);
553 		}
554 	}
555 }
556 
setX(int x)557 void GraphicListBox::setX(int x) {
558 	this->x= x;
559 	graphButton1.setX(x);
560 	if(leftControlled==true) {
561 		graphButton2.setX(x+graphButton1.getW());
562 	}
563 	else {
564 		graphButton2.setX(x+w-graphButton2.getW());
565 	}
566 }
567 
setY(int y)568 void GraphicListBox::setY(int y) {
569 	this->y= y;
570 	graphButton1.setY(y);
571 	graphButton2.setY(y);
572 }
573 
setEditable(bool editable)574 void GraphicListBox::setEditable(bool editable){
575     graphButton1.setEditable(editable);
576     graphButton2.setEditable(editable);
577     GraphicComponent::setEditable(editable);
578 }
579 
hasItem(string item) const580 bool GraphicListBox::hasItem(string item) const {
581 	bool result = false;
582 	vector<string>::const_iterator iter= find(items.begin(), items.end(), item);
583 	if(iter != items.end()) {
584 		result = true;
585 	}
586 
587 	return result;
588 }
589 
setSelectedItem(string item,bool errorOnMissing)590 void GraphicListBox::setSelectedItem(string item, bool errorOnMissing){
591 	vector<string>::iterator iter;
592 
593     iter= find(items.begin(), items.end(), item);
594 
595 	if(iter==items.end()) {
596 		if(errorOnMissing == true) {
597 			for(int idx = 0; idx < (int)items.size(); idx++) {
598 				SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\ninstanceName [%s] idx = %d items[idx] = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,instanceName.c_str(),idx,items[idx].c_str());
599 			}
600 
601 		    char szBuf[8096]="";
602 		    snprintf(szBuf,8096,"Value not found in listbox name: [%s] value: %s",this->instanceName.c_str(),item.c_str());
603 			throw megaglest_runtime_error(szBuf);
604 		}
605 	}
606 	else {
607 		setSelectedItemIndex(iter-items.begin());
608 	}
609 
610 }
611 
mouseMove(int x,int y)612 bool GraphicListBox::mouseMove(int x, int y){
613 	if(this->getVisible() == false) {
614 		return false;
615 	}
616 
617 	return
618         graphButton1.mouseMove(x, y) ||
619         graphButton2.mouseMove(x, y);
620 }
621 
mouseClick(int x,int y,string advanceToItemStartingWith)622 bool GraphicListBox::mouseClick(int x, int y,string advanceToItemStartingWith) {
623 	if(this->getVisible() == false) {
624 		return false;
625 	}
626 
627 	if(!items.empty()) {
628 		bool b1= graphButton1.mouseClick(x, y);
629 		bool b2= graphButton2.mouseClick(x, y);
630 
631 		if(b1) {
632 			bool bFound = false;
633 			if(advanceToItemStartingWith != "") {
634 				for(int i = selectedItemIndex - 1; i >= 0; --i) {
635 					string item = items[i];
636 					if((int)translated_items.size() > i) item = translated_items[i];
637 					if(StartsWith(toLower(item),toLower(advanceToItemStartingWith)) == true) {
638 						bFound = true;
639 						selectedItemIndex = i;
640 						break;
641 					}
642 				}
643 				if(bFound == false) {
644 					for(int i = (int)items.size() - 1; i >= selectedItemIndex; --i) {
645 						string item = items[i];
646 						if((int)translated_items.size() > i) item = translated_items[i];
647 						//printf("Trying to match [%s] with item [%s]\n",advanceToItemStartingWith.c_str(),item.c_str());
648 						if(StartsWith(toLower(item),toLower(advanceToItemStartingWith)) == true) {
649 							bFound = true;
650 							selectedItemIndex = i;
651 							break;
652 						}
653 					}
654 				}
655 			}
656 			if(bFound == false) {
657 				selectedItemIndex--;
658 			}
659 			if(selectedItemIndex<0){
660 				selectedItemIndex = (int)items.size()-1;
661 			}
662 		}
663 		else if(b2) {
664 			bool bFound = false;
665 			if(advanceToItemStartingWith != "") {
666 				for(int i = selectedItemIndex + 1; i < (int)items.size(); ++i) {
667 					string item = items[i];
668 					if((int)translated_items.size() > i) item = translated_items[i];
669 					//printf("Trying to match [%s] with item [%s]\n",advanceToItemStartingWith.c_str(),item.c_str());
670 					if(StartsWith(toLower(item),toLower(advanceToItemStartingWith)) == true) {
671 						bFound = true;
672 						selectedItemIndex = i;
673 						break;
674 					}
675 				}
676 				if(bFound == false) {
677 					for(int i = 0; i <= selectedItemIndex; ++i) {
678 						string item = items[i];
679 						if((int)translated_items.size() > i) item = translated_items[i];
680 						//printf("Trying to match [%s] with item [%s]\n",advanceToItemStartingWith.c_str(),item.c_str());
681 						if(StartsWith(toLower(item),toLower(advanceToItemStartingWith)) == true) {
682 							bFound = true;
683 							selectedItemIndex = i;
684 							break;
685 						}
686 					}
687 				}
688 			}
689 			if(bFound == false) {
690 				selectedItemIndex++;
691 			}
692 			if(selectedItemIndex >= (int)items.size()) {
693 				selectedItemIndex=0;
694 			}
695 		}
696 		setText(getSelectedItem());
697 
698 		return b1 || b2;
699 	}
700 	return false;
701 }
702 
703 // =====================================================
704 //	class GraphicMessageBox
705 // =====================================================
706 
707 const int GraphicMessageBox::defH= 280;
708 const int GraphicMessageBox::defW= 350;
709 
GraphicMessageBox(std::string containerName,std::string objName)710 GraphicMessageBox::GraphicMessageBox(std::string containerName, std::string objName) :
711 	GraphicComponent(containerName, objName) {
712 	header= "";
713 	autoWordWrap=true;
714 }
715 
~GraphicMessageBox()716 GraphicMessageBox::~GraphicMessageBox(){
717 	removeButtons();
718 }
719 
removeButtons()720 void GraphicMessageBox::removeButtons(){
721 	while(!buttons.empty()){
722 		delete buttons.back();
723 		buttons.pop_back();
724 	}
725 }
726 
init(const string & button1Str,const string & button2Str,int newWidth,int newHeight)727 void GraphicMessageBox::init(const string &button1Str, const string &button2Str, int newWidth, int newHeight){
728 	init(button1Str, newWidth, newHeight);
729 	addButton(button2Str);
730 }
731 
init(const string & button1Str,int newWidth,int newHeight)732 void GraphicMessageBox::init(const string &button1Str, int newWidth, int newHeight){
733 	init(newWidth,newHeight);
734 	removeButtons();
735 	addButton(button1Str);
736 }
737 
init(int newWidth,int newHeight)738 void GraphicMessageBox::init(int newWidth, int newHeight) {
739 	setFont(CoreData::getInstance().getMenuFontNormal());
740 	setFont3D(CoreData::getInstance().getMenuFontNormal3D());
741 
742 	h= (newHeight >= 0 ? newHeight : defH);
743 	w= (newWidth >= 0 ? newWidth : defW);
744 
745 	const Metrics &metrics= Metrics::getInstance();
746 
747 	x= (metrics.getVirtualW() - w) / 2;
748 	y= (metrics.getVirtualH() - h) / 2;
749 }
750 
addButton(const string & buttonStr,int width,int height)751 void GraphicMessageBox::addButton(const string &buttonStr, int width, int height){
752 	GraphicButton *newButton= new GraphicButton(containerName, instanceName + "_Button_" + buttonStr);
753 	newButton->init(0, 0);
754 	newButton->setText(buttonStr);
755 	if(width != -1){
756 		newButton->setW(width);
757 	}
758 	if(height != -1){
759 		newButton->setH(height);
760 	}
761 	buttons.push_back(newButton);
762 	alignButtons();
763 }
764 
alignButtons()765 void GraphicMessageBox::alignButtons(){
766 	int currXPos= 0;
767 	int totalbuttonListLength=0;
768 	int buttonOffset=5;
769 	for(int i= 0; i < getButtonCount(); i++){
770 		GraphicButton *button= getButton(i);
771 		totalbuttonListLength+=button->getW();
772 	}
773 	totalbuttonListLength+=(getButtonCount()-1)*buttonOffset;
774 	currXPos=x+w/2-totalbuttonListLength/2;
775 	for(int i= 0; i < getButtonCount(); i++){
776 		GraphicButton *button= getButton(i);
777 		button->setY(y + 25);
778 		button->setX(currXPos);
779 		currXPos+=button->getW()+buttonOffset;
780 	}
781 }
782 
setX(int x)783 void GraphicMessageBox::setX(int x){
784 	this->x= x;
785 	alignButtons();
786 }
787 
setY(int y)788 void GraphicMessageBox::setY(int y){
789 	this->y= y;
790 	alignButtons();
791 }
792 
mouseMove(int x,int y)793 bool GraphicMessageBox::mouseMove(int x, int y){
794 	if(this->getVisible() == false){
795 		return false;
796 	}
797 	for(int i= 0; i < getButtonCount(); i++){
798 		if(getButton(i)->mouseMove(x, y)){
799 			return true;
800 		}
801 	}
802 	return false;
803 }
804 
mouseClick(int x,int y)805 bool GraphicMessageBox::mouseClick(int x, int y){
806 	if(this->getVisible() == false){
807 		return false;
808 	}
809 
810 	for(int i= 0; i < getButtonCount(); i++){
811 		if(getButton(i)->mouseClick(x, y)){
812 			return true;
813 		}
814 	}
815 	return false;
816 }
817 
mouseClick(int x,int y,int & clickedButton)818 bool GraphicMessageBox::mouseClick(int x, int y, int &clickedButton){
819 	if(this->getVisible() == false){
820 		return false;
821 	}
822 
823 	for(int i= 0; i < getButtonCount(); i++){
824 		if(getButton(i)->mouseClick(x, y)){
825 			clickedButton=i;
826 			return true;
827 		}
828 	}
829 	return false;
830 }
831 
832 // =====================================================
833 //	class GraphicLine
834 // =====================================================
835 
836 const int GraphicLine::defH= 5;
837 const int GraphicLine::defW= 1000;
838 
GraphicLine(std::string containerName,std::string objName)839 GraphicLine::GraphicLine(std::string containerName, std::string objName)
840 : GraphicComponent(containerName, objName) {
841 	horizontal = false;
842 }
843 
init(int x,int y,int w,int h)844 void GraphicLine::init(int x, int y, int w, int h){
845 	GraphicComponent::init(x, y, w, h);
846 	horizontal=true;
847 }
848 
849 // =====================================================
850 //	class GraphicCheckBox
851 // =====================================================
852 
853 const int GraphicCheckBox::defH= 22;
854 const int GraphicCheckBox::defW= 22;
855 
GraphicCheckBox(std::string containerName,std::string objName)856 GraphicCheckBox::GraphicCheckBox(std::string containerName, std::string objName)
857 : GraphicComponent(containerName, objName) {
858 	value = false;
859 	lighted = false;
860 }
861 
init(int x,int y,int w,int h)862 void GraphicCheckBox::init(int x, int y, int w, int h){
863 	GraphicComponent::init(x, y, w, h);
864 	value=true;
865     lighted= false;
866 }
867 
mouseMove(int x,int y)868 bool GraphicCheckBox::mouseMove(int x, int y){
869 	if(this->getVisible() == false) {
870 		return false;
871 	}
872 
873 	bool b= GraphicComponent::mouseMove(x, y);
874     lighted= b;
875     return b;
876 }
877 
mouseClick(int x,int y)878 bool GraphicCheckBox::mouseClick(int x, int y){
879 	bool result=GraphicComponent::mouseClick( x,  y);
880 	if(result == true) {
881     	if(value) {
882     		value=false;
883     	}
884     	else {
885     		value=true;
886     	}
887 	}
888     return result;
889 }
890 
891 // =====================================================
892 //	class GraphicScrollBar
893 // =====================================================
894 
895 const int GraphicScrollBar::defThickness=20;
896 const int GraphicScrollBar::defLength= 200;
897 
GraphicScrollBar(std::string containerName,std::string objName)898 GraphicScrollBar::GraphicScrollBar(std::string containerName, std::string objName)
899 : GraphicComponent(containerName, objName) {
900 	lighted = false;
901 	activated = false;
902 	horizontal = false;
903 	elementCount = 0;
904 	visibleSize = 0;
905 	visibleStart = 0;
906 
907 	// position on component for renderer
908 	visibleCompPosStart = 0;
909 	visibleCompPosEnd = 0;
910 }
911 
init(int x,int y,bool horizontal,int length,int thickness)912 void GraphicScrollBar::init(int x, int y, bool horizontal,int length, int thickness){
913 	GraphicComponent::init(x, y, horizontal?length:thickness,horizontal?thickness:length );
914 	this->horizontal=horizontal;
915 	this->elementCount=1;
916 	this->visibleSize=1;
917 	this->visibleStart=0;
918 	this->visibleCompPosStart=0;
919 	this->visibleCompPosEnd=length;
920 	activated = false;
921 	lighted = false;
922 }
923 
mouseDown(int x,int y)924 bool GraphicScrollBar::mouseDown(int x, int y) {
925 	if(getVisible() && getEnabled() && getEditable())
926 	{
927 		if(activated && elementCount>0)
928 		{
929 			if( elementCount>visibleSize) {
930 				int pos;
931 				if(horizontal){
932 					pos=x-this->x;
933 				}
934 				else {
935 					// invert the clicked point ( y is from bottom to top normally )
936 					pos=getLength()-(y-this->y);
937 				}
938 				float partSize=(float)getLength()/(float)elementCount;
939 				float visiblePartSize=partSize*(float)visibleSize;
940 				float startPos=((float)pos)-visiblePartSize/2;
941 
942 				visibleStart=startPos/partSize;
943 				setVisibleStart(visibleStart);
944 
945 			}
946 		}
947 	}
948 	return false;
949 }
950 
mouseUp(int x,int y)951 void GraphicScrollBar::mouseUp(int x, int y) {
952 	activated = false;
953 	lighted = false;
954 }
955 
setVisibleStart(int vs)956 void GraphicScrollBar::setVisibleStart(int vs){
957 	visibleStart=vs;
958 
959 	if(visibleStart>elementCount-visibleSize) {
960 		visibleStart=elementCount-visibleSize;
961 	}
962 	if(visibleStart<0) {
963 		visibleStart=0;
964 	}
965 	float partSize = 0.f;
966 	if(elementCount > 0) {
967 		partSize = (float)getLength()/(float)elementCount;
968 	}
969 	visibleCompPosStart=visibleStart*partSize;
970 	visibleCompPosEnd=visibleStart*partSize+visibleSize*partSize;
971 	if(visibleCompPosEnd>getLength()) {
972 		visibleCompPosEnd=getLength();
973 	}
974 	if(!horizontal) {
975 		// invert the display ( y is from bottom to top normally )
976 		visibleCompPosStart=getLength()-visibleCompPosStart;
977 		visibleCompPosEnd=getLength()-visibleCompPosEnd;
978 	}
979 }
980 
setElementCount(int elementCount)981 void GraphicScrollBar::setElementCount(int elementCount){
982 	this->elementCount=elementCount;
983 	setVisibleStart(getVisibleStart());
984 }
985 
setVisibleSize(int visibleSize)986 void GraphicScrollBar::setVisibleSize(int visibleSize){
987 	this->visibleSize=visibleSize;
988 	setVisibleStart(getVisibleStart());
989 }
990 
991 
mouseClick(int x,int y)992 bool GraphicScrollBar::mouseClick(int x, int y){
993 	bool result=GraphicComponent::mouseClick( x,  y);
994 	if(result) {
995 		activated = true;
996 		lighted = true;
997 		mouseDown( x,  y);
998 	}
999 	return result;
1000 }
1001 
1002 
mouseMove(int x,int y)1003 bool GraphicScrollBar::mouseMove(int x, int y){
1004 	if(this->getVisible() == false) {
1005 		return false;
1006 	}
1007 
1008 	bool inScrollBar = GraphicComponent::mouseMove(x, y);
1009 	if (activated) {
1010 		lighted = true;
1011 	} else {
1012 		lighted = inScrollBar;
1013 	}
1014 	return inScrollBar;
1015 }
1016 
getLength() const1017 int GraphicScrollBar::getLength() const {
1018 	return horizontal?getW():getH();
1019 }
1020 
getThickness() const1021 int GraphicScrollBar::getThickness() const {
1022 	return horizontal?getH():getW();
1023 }
1024 
arrangeComponents(vector<GraphicComponent * > & gcs)1025 void GraphicScrollBar::arrangeComponents(vector<GraphicComponent *> &gcs) {
1026 	if(getElementCount()!=0 ) {
1027     	for(int i = getVisibleStart(); i <= getVisibleEnd(); ++i) {
1028     		if(horizontal){
1029     			gcs[i]->setX(getX()+getLength()-gcs[i]->getW()-gcs[i]->getW()*(i-getVisibleStart()));
1030     		}
1031     		else {
1032     			gcs[i]->setY(getY()+getLength()-gcs[i]->getH()-gcs[i]->getH()*(i-getVisibleStart()));
1033     		}
1034     	}
1035     }
1036 }
1037 // ===========================================================
1038 // 	class PopupMenu
1039 // ===========================================================
1040 
1041 const int PopupMenu::defH= 240;
1042 const int PopupMenu::defW= 350;
1043 
PopupMenu(std::string containerName,std::string objName)1044 PopupMenu::PopupMenu(std::string containerName, std::string objName) : GraphicComponent(containerName, objName, false) {
1045 	registerGraphicComponentOnlyFontCallbacks(containerName,objName);
1046 
1047 	h= defH;
1048 	w= defW;
1049 }
1050 
~PopupMenu()1051 PopupMenu::~PopupMenu() {
1052 
1053 }
1054 
init(string menuHeader,std::vector<string> menuItems)1055 void PopupMenu::init(string menuHeader,std::vector<string> menuItems) {
1056 	header = menuHeader;
1057 
1058 	setFont(CoreData::getInstance().getMenuFontNormal());
1059 	setFont3D(CoreData::getInstance().getMenuFontNormal3D());
1060 
1061 	buttons.clear();
1062 
1063 	const Metrics &metrics= Metrics::getInstance();
1064 
1065 	x= (metrics.getVirtualW()-w)/2;
1066 	y= (metrics.getVirtualH()-h)/2;
1067 
1068 	int textHeight = GraphicButton::defH;
1069 	int textHeightSpacing = 6;
1070 
1071 	int maxButtonWidth = -1;
1072 	for(unsigned int i = 0; i < menuItems.size(); ++i) {
1073 		int currentButtonWidth = -1;
1074 		if(font3D != NULL && Shared::Graphics::Font::forceLegacyFonts == false) {
1075 			FontMetrics *fontMetrics= font3D->getMetrics();
1076 			if(fontMetrics) {
1077 				currentButtonWidth = fontMetrics->getTextWidth(menuItems[i]);
1078 			}
1079 		}
1080 		else if(font) {
1081 			FontMetrics *fontMetrics= font->getMetrics();
1082 			if(fontMetrics) {
1083 				currentButtonWidth = fontMetrics->getTextWidth(menuItems[i]);
1084 			}
1085 		}
1086 
1087 		if(maxButtonWidth < 0 || currentButtonWidth > maxButtonWidth) {
1088 			maxButtonWidth = currentButtonWidth + textHeightSpacing;
1089 		}
1090 	}
1091 
1092 	int yStartOffset = y + h - (textHeight * 2);
1093 
1094 	if(maxButtonWidth >= w) {
1095 		w = maxButtonWidth + textHeightSpacing;
1096 		x= (metrics.getVirtualW()-w)/2;
1097 	}
1098 
1099 	int offsetH = (yStartOffset - y);
1100 	int maxH = (offsetH + (((int)menuItems.size() -1 ) * (textHeight + textHeightSpacing)));
1101 	if(maxH >= h) {
1102 		h = maxH;
1103 		y= (metrics.getVirtualH()-h)/2;
1104 		yStartOffset = y + h - (textHeight * 2);
1105 	}
1106 
1107 	for(unsigned int i = 0; i < menuItems.size(); ++i) {
1108 		GraphicButton button(containerName, instanceName + "_Popup_Button_" + menuItems[i],false);
1109 		button.registerGraphicComponentOnlyFontCallbacks(containerName, instanceName + "_Popup_Button_" + menuItems[i]);
1110 		button.init(x+(w-maxButtonWidth)/2, yStartOffset - (i*(textHeight + textHeightSpacing)));
1111 		button.setText(menuItems[i]);
1112 		button.setW(maxButtonWidth);
1113 
1114 		buttons.push_back(button);
1115 	}
1116 }
1117 
setX(int x)1118 void PopupMenu::setX(int x) {
1119 	this->x= x;
1120 
1121 	for(unsigned int i = 0; i < buttons.size(); ++i) {
1122 		GraphicButton &button = buttons[i];
1123 		button.init(x+(w-GraphicButton::defW)/4, y+25 + (i*25));
1124 	}
1125 }
1126 
setY(int y)1127 void PopupMenu::setY(int y) {
1128 	this->y= y;
1129 
1130 	for(unsigned int i = 0; i < buttons.size(); ++i) {
1131 		GraphicButton &button = buttons[i];
1132 		button.init(x+(w-GraphicButton::defW)/4, y+25 + (i*25));
1133 	}
1134 }
1135 
mouseMove(int x,int y)1136 bool PopupMenu::mouseMove(int x, int y){
1137 	if(this->getVisible() == false) {
1138 		return false;
1139 	}
1140 
1141 	for(unsigned int i = 0; i < buttons.size(); ++i) {
1142 		GraphicButton &button = buttons[i];
1143 		if(button.mouseMove(x, y)) {
1144 			return true;
1145 		}
1146 	}
1147 
1148 	return false;
1149 }
1150 
mouseClick(int x,int y)1151 bool PopupMenu::mouseClick(int x, int y) {
1152 	if(this->getVisible() == false) {
1153 		return false;
1154 	}
1155 
1156 	for(unsigned int i = 0; i < buttons.size(); ++i) {
1157 		GraphicButton &button = buttons[i];
1158 		if(button.mouseClick(x, y)) {
1159 			return true;
1160 		}
1161 	}
1162 	return false;
1163 }
1164 
mouseClickedMenuItem(int x,int y)1165 std::pair<int,string> PopupMenu::mouseClickedMenuItem(int x, int y) {
1166 	std::pair<int,string> result;
1167 	for(unsigned int i = 0; i < buttons.size(); ++i) {
1168 		GraphicButton &button = buttons[i];
1169 		if(button.mouseClick(x, y)) {
1170 			result.first = i;
1171 			result.second = buttons[i].getText();
1172 			break;
1173 		}
1174 	}
1175 
1176 	return result;
1177 }
1178 
1179 }}//end namespace
1180