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