1 /*
2  * Copyright 2010-2014 OpenXcom Developers.
3  *
4  * This file is part of OpenXcom.
5  *
6  * OpenXcom is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * OpenXcom is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "GraphsState.h"
20 #include <sstream>
21 #include "../Engine/Game.h"
22 #include "../Resource/ResourcePack.h"
23 #include "../Engine/Palette.h"
24 #include "../Engine/Surface.h"
25 #include "../Engine/Screen.h"
26 #include "../Engine/InteractiveSurface.h"
27 #include "../Savegame/Country.h"
28 #include "../Savegame/Region.h"
29 #include "../Ruleset/RuleCountry.h"
30 #include "../Ruleset/RuleRegion.h"
31 #include "../Interface/Text.h"
32 #include "../Engine/Language.h"
33 #include "../Interface/TextButton.h"
34 #include "../Interface/ToggleTextButton.h"
35 #include "../Savegame/GameTime.h"
36 #include "../Savegame/SavedGame.h"
37 #include "../Interface/TextList.h"
38 #include "../Engine/Action.h"
39 #include "../Engine/Options.h"
40 
41 namespace OpenXcom
42 {
43 
44 struct GraphButInfo
45 {
46 	LocalizedText _name;
47 	int _color;
48 	bool _pushed;
GraphButInfoOpenXcom::GraphButInfo49 	GraphButInfo(const LocalizedText& name, Uint8 color): _name(name), _color(color), _pushed(false) {}
50 };
51 /**
52  * Initializes all the elements in the Graphs screen.
53  * @param game Pointer to the core game.
54  */
GraphsState(Game * game)55 GraphsState::GraphsState(Game *game) : State(game), _butRegionsOffset(0), _butCountriesOffset(0)
56 {
57 	// Create objects
58 	_bg = new InteractiveSurface(320, 200, 0, 0);
59 	_bg->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELUP);
60 	_bg->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELDOWN);
61 	_btnUfoRegion = new InteractiveSurface(32, 24, 96, 0);
62 	_btnUfoCountry = new InteractiveSurface(32, 24, 128, 0);
63 	_btnXcomRegion = new InteractiveSurface(32, 24, 160, 0);
64 	_btnXcomCountry = new InteractiveSurface(32, 24, 192, 0);
65 	_btnIncome = new InteractiveSurface(32, 24, 224, 0);
66 	_btnFinance = new InteractiveSurface(32, 24, 256, 0);
67 	_btnGeoscape = new InteractiveSurface(32, 24, 288, 0);
68 	_txtTitle = new Text(220, 16, 100, 28);
69 	_txtFactor = new Text(38, 11, 96, 28);
70 	_txtMonths = new TextList(205, 8, 115, 183);
71 	_txtYears = new TextList(200, 8, 121, 191);
72 
73 	// Set palette
74 	setPalette("PAL_GRAPHS");
75 
76 	//add all our elements
77 	add(_bg);
78 	add(_btnUfoRegion);
79 	add(_btnUfoCountry);
80 	add(_btnXcomRegion);
81 	add(_btnXcomCountry);
82 	add(_btnIncome);
83 	add(_btnFinance);
84 	add(_btnGeoscape);
85 	add(_txtMonths);
86 	add(_txtYears);
87 	add(_txtTitle);
88 	add(_txtFactor);
89 	for (int scaleText = 0; scaleText != 10; ++scaleText)
90 	{
91 		_txtScale.push_back(new Text(42, 16, 80, 171 - (scaleText*14)));
92 		add(_txtScale.at(scaleText));
93 	}
94 
95 	//create buttons (sooooo many buttons)
96 	size_t offset = 0;
97 	for (std::vector<Region *>::iterator iter = _game->getSavedGame()->getRegions()->begin(); iter != _game->getSavedGame()->getRegions()->end(); ++iter)
98 	{
99 		// always save in toggles all the regions
100 		_regionToggles.push_back(new GraphButInfo(tr((*iter)->getRules()->getType()) , -42 + (4*offset)));
101 		// initially add the GRAPH_MAX_BUTTONS having the first regions information
102 		if(offset < GRAPH_MAX_BUTTONS)
103 		{
104 			_btnRegions.push_back(new ToggleTextButton(80, 11, 0, offset*11));
105 			_btnRegions.at(offset)->setColor(Palette::blockOffset(9)+7);
106 			_btnRegions.at(offset)->setInvertColor(-42 + (4*offset));
107 			_btnRegions.at(offset)->setText(tr((*iter)->getRules()->getType()));
108 			_btnRegions.at(offset)->onMousePress((ActionHandler)&GraphsState::btnRegionListClick);
109 			_btnRegions.at(offset)->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELUP);
110 			_btnRegions.at(offset)->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELDOWN);
111 			add(_btnRegions.at(offset));
112 		}
113 		_alienRegionLines.push_back(new Surface(320,200,0,0));
114 		add(_alienRegionLines.at(offset));
115 		_xcomRegionLines.push_back(new Surface(320,200,0,0));
116 		add(_xcomRegionLines.at(offset));
117 
118 		++offset;
119 	}
120 
121 	if(_regionToggles.size() < GRAPH_MAX_BUTTONS)
122 		_btnRegionTotal = new ToggleTextButton(80, 11, 0, _regionToggles.size()*11);
123 	else
124 		_btnRegionTotal = new ToggleTextButton(80, 11, 0, GRAPH_MAX_BUTTONS*11);
125 	_regionToggles.push_back(new GraphButInfo(tr("STR_TOTAL_UC"), 18));
126 	_btnRegionTotal->onMousePress((ActionHandler)&GraphsState::btnRegionListClick);
127 	_btnRegionTotal->setColor(Palette::blockOffset(9)+7);
128 	_btnRegionTotal->setInvertColor(18);
129 	_btnRegionTotal->setText(tr("STR_TOTAL_UC"));
130 	_alienRegionLines.push_back(new Surface(320,200,0,0));
131 	add(_alienRegionLines.at(offset));
132 	_xcomRegionLines.push_back(new Surface(320,200,0,0));
133 	add(_xcomRegionLines.at(offset));
134 	add(_btnRegionTotal);
135 
136 	offset = 0;
137 	for (std::vector<Country *>::iterator iter = _game->getSavedGame()->getCountries()->begin(); iter != _game->getSavedGame()->getCountries()->end(); ++iter)
138 	{
139 		// always save in toggles all the countries
140 		_countryToggles.push_back(new GraphButInfo(tr((*iter)->getRules()->getType()) , -42 + (4*offset)));
141 		// initially add the GRAPH_MAX_BUTTONS having the first countries information
142 		if(offset < GRAPH_MAX_BUTTONS)
143 		{
144 			_btnCountries.push_back(new ToggleTextButton(80, 11, 0, offset*11));
145 			_btnCountries.at(offset)->setColor(Palette::blockOffset(9)+7);
146 			_btnCountries.at(offset)->setInvertColor(-42 + (4*offset));
147 			_btnCountries.at(offset)->setText(tr((*iter)->getRules()->getType()));
148 			_btnCountries.at(offset)->onMousePress((ActionHandler)&GraphsState::btnCountryListClick);
149 			_btnCountries.at(offset)->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELUP);
150 			_btnCountries.at(offset)->onMousePress((ActionHandler)&GraphsState::shiftButtons, SDL_BUTTON_WHEELDOWN);
151 			add(_btnCountries.at(offset));
152 		}
153 		_alienCountryLines.push_back(new Surface(320,200,0,0));
154 		add(_alienCountryLines.at(offset));
155 		_xcomCountryLines.push_back(new Surface(320,200,0,0));
156 		add(_xcomCountryLines.at(offset));
157 		_incomeLines.push_back(new Surface(320,200,0,0));
158 		add(_incomeLines.at(offset));
159 
160 		++offset;
161 	}
162 
163 	if(_countryToggles.size() < GRAPH_MAX_BUTTONS)
164 		_btnCountryTotal = new ToggleTextButton(80, 11, 0, _countryToggles.size()*11);
165 	else
166 		_btnCountryTotal = new ToggleTextButton(80, 11, 0, GRAPH_MAX_BUTTONS*11);
167 	_countryToggles.push_back(new GraphButInfo(tr("STR_TOTAL_UC"), 22));
168 	_btnCountryTotal->onMousePress((ActionHandler)&GraphsState::btnCountryListClick);
169 	_btnCountryTotal->setColor(Palette::blockOffset(9)+7);
170     _btnCountryTotal->setInvertColor(22);
171 	_btnCountryTotal->setText(tr("STR_TOTAL_UC"));
172 	_alienCountryLines.push_back(new Surface(320,200,0,0));
173 	add(_alienCountryLines.at(offset));
174 	_xcomCountryLines.push_back(new Surface(320,200,0,0));
175 	add(_xcomCountryLines.at(offset));
176 	_incomeLines.push_back(new Surface(320,200,0,0));
177 	add(_incomeLines.at(offset));
178 	add(_btnCountryTotal);
179 
180 
181 	for (int iter = 0; iter != 5; ++iter)
182 	{
183 		offset = iter;
184 		_btnFinances.push_back(new ToggleTextButton(80, 11, 0, offset*11));
185 		_financeToggles.push_back(false);
186 		_btnFinances.at(offset)->setColor(Palette::blockOffset(9)+7);
187         _btnFinances.at(offset)->setInvertColor(-42 + (4*offset));
188 		_btnFinances.at(offset)->onMousePress((ActionHandler)&GraphsState::btnFinanceListClick);
189 		add(_btnFinances.at(offset));
190 		_financeLines.push_back(new Surface(320,200,0,0));
191 		add(_financeLines.at(offset));
192 	}
193 
194 	_btnFinances.at(0)->setText(tr("STR_INCOME"));
195 	_btnFinances.at(1)->setText(tr("STR_EXPENDITURE"));
196 	_btnFinances.at(2)->setText(tr("STR_MAINTENANCE"));
197 	_btnFinances.at(3)->setText(tr("STR_BALANCE"));
198 	_btnFinances.at(4)->setText(tr("STR_SCORE"));
199 
200 	// load back the button states
201 	std::string graphRegionToggles = _game->getSavedGame()->getGraphRegionToggles();
202 	std::string graphCountryToggles = _game->getSavedGame()->getGraphCountryToggles();
203 	std::string graphFinanceToggles = _game->getSavedGame()->getGraphFinanceToggles();
204 	while (graphRegionToggles.size() < _regionToggles.size()) graphRegionToggles.push_back('0');
205 	while (graphCountryToggles.size() < _countryToggles.size()) graphCountryToggles.push_back('0');
206 	while (graphFinanceToggles.size() < _financeToggles.size()) graphFinanceToggles.push_back('0');
207 	for (size_t i = 0; i < _regionToggles.size(); ++i)
208 	{
209 		_regionToggles[i]->_pushed = ('0'==graphRegionToggles[i]) ? false : true;
210 		if (_regionToggles.size()-1 == i)
211 			_btnRegionTotal->setPressed(_regionToggles[i]->_pushed);
212 		else if(i < GRAPH_MAX_BUTTONS)
213 			_btnRegions.at(i)->setPressed(_regionToggles[i]->_pushed);
214 	}
215 	for (size_t i = 0; i < _countryToggles.size(); ++i)
216 	{
217 		_countryToggles[i]->_pushed = ('0'==graphCountryToggles[i]) ? false : true;
218 		if (_countryToggles.size()-1 == i)
219 			_btnCountryTotal->setPressed(_countryToggles[i]->_pushed);
220 		else if(i < GRAPH_MAX_BUTTONS)
221 			_btnCountries.at(i)->setPressed(_countryToggles[i]->_pushed);
222 	}
223 	for (size_t i = 0; i < _financeToggles.size(); ++i)
224 	{
225 		_financeToggles[i] = ('0'==graphFinanceToggles[i]) ? false : true;
226 		_btnFinances.at(i)->setPressed(_financeToggles[i]);
227 	}
228 
229 	// set up the grid
230 	_bg->drawRect(125, 49, 188, 127, Palette::blockOffset(10));
231 
232 	for (int grid = 0; grid !=5; ++grid)
233 	{
234 		for (int y = 50 + grid; y <= 163 + grid; y += 14)
235 		{
236 			for (int x = 126 + grid; x <= 297 + grid; x += 17)
237 			{
238 				Uint8 color = Palette::blockOffset(10)+grid+1;
239 				if (grid == 4)
240 				{
241 					color = 0;
242 				}
243 				_bg->drawRect(x, y, 16 - (grid*2), 13 - (grid*2), color);
244 			}
245 		}
246 	}
247 
248 	//set up the horizontal measurement units
249 	std::string months[] = {"STR_JAN", "STR_FEB", "STR_MAR", "STR_APR", "STR_MAY", "STR_JUN", "STR_JUL", "STR_AUG", "STR_SEP", "STR_OCT", "STR_NOV", "STR_DEC"};
250 	int month = _game->getSavedGame()->getTime()->getMonth();
251 	// i know using textlist for this is ugly and brutal, but YOU try getting this damn text to line up.
252 	// also, there's nothing wrong with being ugly or brutal, you should learn tolerance.
253 	_txtMonths->setColumns(12, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17);
254 	_txtMonths->addRow(12, L" ", L" ", L" ", L" ", L" ", L" ", L" ", L" ", L" ", L" ", L" ", L" ");
255 	_txtMonths->setRowColor(0, Palette::blockOffset(6)+7);
256 	_txtYears->setColumns(6, 34, 34, 34, 34, 34, 34);
257 	_txtYears->addRow(6, L" ", L" ", L" ", L" ", L" ", L" ");
258 	_txtYears->setRowColor(0, Palette::blockOffset(6)+7);
259 
260 	for (int iter = 0; iter != 12; ++iter)
261 	{
262 		if (month > 11)
263 		{
264 			month = 0;
265 			std::wostringstream ss;
266 			ss << _game->getSavedGame()->getTime()->getYear();
267 			_txtYears->setCellText(0, iter/2, ss.str());
268 			if (iter > 2)
269 			{
270 				std::wostringstream ss2;
271 				ss2 << (_game->getSavedGame()->getTime()->getYear()-1);
272 				_txtYears->setCellText(0, 0, ss2.str());
273 			}
274 		}
275 		_txtMonths->setCellText(0, iter, tr(months[month]));
276 		++month;
277 	}
278 
279 	// set up the vertical measurement units
280 	for (std::vector<Text *>::iterator iter = _txtScale.begin(); iter != _txtScale.end(); ++iter)
281 	{
282 		(*iter)->setAlign(ALIGN_RIGHT);
283 		(*iter)->setColor(Palette::blockOffset(6)+7);
284 	}
285 	btnUfoRegionClick(0);
286 
287 	// Set up objects
288 	_game->getResourcePack()->getSurface("GRAPHS.SPK")->blit(_bg);
289 	_txtTitle->setAlign(ALIGN_CENTER);
290 	_txtTitle->setColor(Palette::blockOffset(8)+7);
291 
292 	_txtFactor->setText(L"$1000's");
293 	_txtFactor->setColor(Palette::blockOffset(8)+7);
294 
295 	// Set up buttons
296 	_btnUfoRegion->onMousePress((ActionHandler)&GraphsState::btnUfoRegionClick);
297 	_btnUfoCountry->onMousePress((ActionHandler)&GraphsState::btnUfoCountryClick);
298 	_btnXcomRegion->onMousePress((ActionHandler)&GraphsState::btnXcomRegionClick);
299 	_btnXcomCountry->onMousePress((ActionHandler)&GraphsState::btnXcomCountryClick);
300 	_btnIncome->onMousePress((ActionHandler)&GraphsState::btnIncomeClick);
301 	_btnFinance->onMousePress((ActionHandler)&GraphsState::btnFinanceClick);
302 	_btnGeoscape->onMousePress((ActionHandler)&GraphsState::btnGeoscapeClick);
303 	_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnGeoscapeClick, Options::keyCancel);
304 	_btnGeoscape->onKeyboardPress((ActionHandler)&GraphsState::btnGeoscapeClick, Options::keyGeoGraphs);
305 
306 	centerAllSurfaces();
307 }
308 
309 /**
310  *
311  */
~GraphsState()312 GraphsState::~GraphsState()
313 {
314 	std::string graphRegionToggles = "";
315 	std::string graphCountryToggles = "";
316 	std::string graphFinanceToggles = "";
317 	for (size_t i = 0; i < _regionToggles.size(); ++i)
318 	{
319 		graphRegionToggles.push_back(_regionToggles[i]->_pushed ? '1' : '0');
320 		delete _regionToggles[i];
321 	}
322 	for (size_t i = 0; i < _countryToggles.size(); ++i)
323 	{
324 		graphCountryToggles.push_back(_countryToggles[i]->_pushed ? '1' : '0');
325 		delete _countryToggles[i];
326 	}
327 	for (size_t i = 0; i < _financeToggles.size(); ++i)
328 	{
329 		graphFinanceToggles.push_back(_financeToggles[i] ? '1' : '0');
330 	}
331 	_game->getSavedGame()->setGraphRegionToggles(graphRegionToggles);
332 	_game->getSavedGame()->setGraphCountryToggles(graphCountryToggles);
333 	_game->getSavedGame()->setGraphFinanceToggles(graphFinanceToggles);
334 }
335 
336 /**
337  * Returns to the previous screen.
338  * @param action Pointer to an action.
339  */
btnGeoscapeClick(Action *)340 void GraphsState::btnGeoscapeClick(Action *)
341 {
342 	_game->popState();
343 }
344 
345 /**
346  * Switches to the UFO Region Activity screen.
347  * @param action Pointer to an action.
348  */
btnUfoRegionClick(Action *)349 void GraphsState::btnUfoRegionClick(Action *)
350 {
351 	_alien = true;
352 	_income = false;
353 	_country = false;
354 	_finance = false;
355 	resetScreen();
356 	drawLines();
357 	for (std::vector<ToggleTextButton *>::iterator iter = _btnRegions.begin(); iter != _btnRegions.end(); ++iter)
358 	{
359 		(*iter)->setVisible(true);
360 	}
361 	_btnRegionTotal->setVisible(true);
362 	_txtTitle->setBig();
363 	_txtTitle->setText(tr("STR_UFO_ACTIVITY_IN_AREAS"));
364 }
365 
366 /**
367  * Switches to the UFO Country activity screen.
368  * @param action Pointer to an action.
369  */
btnUfoCountryClick(Action *)370 void GraphsState::btnUfoCountryClick(Action *)
371 {
372 	_alien = true;
373 	_income = false;
374 	_country = true;
375 	_finance = false;
376 	resetScreen();
377 	drawLines();
378 	for (std::vector<ToggleTextButton *>::iterator iter = _btnCountries.begin(); iter != _btnCountries.end(); ++iter)
379 	{
380 		(*iter)->setVisible(true);
381 	}
382 	_btnCountryTotal->setVisible(true);
383 	_txtTitle->setBig();
384 	_txtTitle->setText(tr("STR_UFO_ACTIVITY_IN_COUNTRIES"));
385 }
386 
387 /**
388  * Switches to the XCom Region activity screen.
389  * @param action Pointer to an action.
390  */
btnXcomRegionClick(Action *)391 void GraphsState::btnXcomRegionClick(Action *)
392 {
393 	_alien = false;
394 	_income = false;
395 	_country = false;
396 	_finance = false;
397 	resetScreen();
398 	drawLines();
399 	for (std::vector<ToggleTextButton *>::iterator iter = _btnRegions.begin(); iter != _btnRegions.end(); ++iter)
400 	{
401 		(*iter)->setVisible(true);
402 	}
403 	_btnRegionTotal->setVisible(true);
404 	_txtTitle->setBig();
405 	_txtTitle->setText(tr("STR_XCOM_ACTIVITY_IN_AREAS"));
406 }
407 
408 /**
409  * Switches to the XCom Country activity screen.
410  * @param action Pointer to an action.
411  */
btnXcomCountryClick(Action *)412 void GraphsState::btnXcomCountryClick(Action *)
413 {
414 	_alien = false;
415 	_income = false;
416 	_country = true;
417 	_finance = false;
418 	resetScreen();
419 	drawLines();
420 	for (std::vector<ToggleTextButton *>::iterator iter = _btnCountries.begin(); iter != _btnCountries.end(); ++iter)
421 	{
422 		(*iter)->setVisible(true);
423 	}
424 	_btnCountryTotal->setVisible(true);
425 	_txtTitle->setBig();
426 	_txtTitle->setText(tr("STR_XCOM_ACTIVITY_IN_COUNTRIES"));
427 }
428 
429 /**
430  * Switches to the Income screen.
431  * @param action Pointer to an action.
432  */
btnIncomeClick(Action *)433 void GraphsState::btnIncomeClick(Action *)
434 {
435 	_alien = false;
436 	_income = true;
437 	_country = true;
438 	_finance = false;
439 	resetScreen();
440 	drawLines();
441 	_txtFactor->setVisible(true);
442 	for (std::vector<ToggleTextButton *>::iterator iter = _btnCountries.begin(); iter != _btnCountries.end(); ++iter)
443 	{
444 		(*iter)->setVisible(true);
445 	}
446 	_btnCountryTotal->setVisible(true);
447 	_txtTitle->setBig();
448 	_txtTitle->setText(tr("STR_INCOME"));
449 }
450 
451 /**
452  * Switches to the Finances screen.
453  * @param action Pointer to an action.
454  */
btnFinanceClick(Action *)455 void GraphsState::btnFinanceClick(Action *)
456 {
457 	_alien = false;
458 	_income = false;
459 	_country = false;
460 	_finance = true;
461 	resetScreen();
462 	drawLines();
463 
464 	for (std::vector<ToggleTextButton *>::iterator iter = _btnFinances.begin(); iter != _btnFinances.end(); ++iter)
465 	{
466 		(*iter)->setVisible(true);
467 	}
468 	_txtTitle->setBig();
469 	_txtTitle->setText(tr("STR_FINANCE"));
470 
471 }
472 
473 /**
474  * Handles a click on a region button.
475  * @param action Pointer to an action.
476  */
btnRegionListClick(Action * action)477 void GraphsState::btnRegionListClick(Action * action)
478 {
479 	size_t number = (action->getSender()->getY()-_game->getScreen()->getDY())/11;
480 	ToggleTextButton *button = 0;
481 
482 	if ((_regionToggles.size() <= GRAPH_MAX_BUTTONS + 1 && number == _regionToggles.size()-1)||(_regionToggles.size() > GRAPH_MAX_BUTTONS + 1 && number == GRAPH_MAX_BUTTONS))
483 	{
484 		button = _btnRegionTotal;
485 	}
486 	else
487 	{
488 		button = _btnRegions.at(number);
489 	}
490 
491 	_regionToggles.at(number+_butRegionsOffset)->_pushed = button->getPressed();
492 
493 	drawLines();
494 }
495 
496 /**
497  * Handles a click on a country button.
498  * @param action Pointer to an action.
499  */
btnCountryListClick(Action * action)500 void GraphsState::btnCountryListClick(Action * action)
501 {
502 	size_t number = (action->getSender()->getY()-_game->getScreen()->getDY())/11;
503 	ToggleTextButton *button = 0;
504 
505 	if ((_countryToggles.size() <= GRAPH_MAX_BUTTONS + 1 && number == _countryToggles.size()-1)||(_countryToggles.size() > GRAPH_MAX_BUTTONS + 1 && number == GRAPH_MAX_BUTTONS))
506 	{
507 		button = _btnCountryTotal;
508 	}
509 	else
510 	{
511 		button = _btnCountries.at(number);
512 	}
513 
514 	_countryToggles.at(number+_butCountriesOffset)->_pushed = button->getPressed();
515 
516 	drawLines();
517 }
518 
519 /**
520  * handles a click on a finances button.
521  * @param action Pointer to an action.
522  */
btnFinanceListClick(Action * action)523 void GraphsState::btnFinanceListClick(Action *action)
524 {
525 	size_t number = (action->getSender()->getY()-_game->getScreen()->getDY())/11;
526 	ToggleTextButton *button = _btnFinances.at(number);
527 
528 	_financeLines.at(number)->setVisible(!_financeToggles.at(number));
529 	_financeToggles.at(number) = button->getPressed();
530 
531 	drawLines();
532 }
533 
534 /**
535  * remove all elements from view
536  */
resetScreen()537 void GraphsState::resetScreen()
538 {
539 	for (std::vector<Surface *>::iterator iter = _alienRegionLines.begin(); iter != _alienRegionLines.end(); ++iter)
540 	{
541 		(*iter)->setVisible(false);
542 	}
543 	for (std::vector<Surface *>::iterator iter = _alienCountryLines.begin(); iter != _alienCountryLines.end(); ++iter)
544 	{
545 		(*iter)->setVisible(false);
546 	}
547 	for (std::vector<Surface *>::iterator iter = _xcomRegionLines.begin(); iter != _xcomRegionLines.end(); ++iter)
548 	{
549 		(*iter)->setVisible(false);
550 	}
551 	for (std::vector<Surface *>::iterator iter = _xcomCountryLines.begin(); iter != _xcomCountryLines.end(); ++iter)
552 	{
553 		(*iter)->setVisible(false);
554 	}
555 	for (std::vector<Surface *>::iterator iter = _incomeLines.begin(); iter != _incomeLines.end(); ++iter)
556 	{
557 		(*iter)->setVisible(false);
558 	}
559 	for (std::vector<Surface *>::iterator iter = _financeLines.begin(); iter != _financeLines.end(); ++iter)
560 	{
561 		(*iter)->setVisible(false);
562 	}
563 
564 
565 	for (std::vector<ToggleTextButton *>::iterator iter = _btnRegions.begin(); iter != _btnRegions.end(); ++iter)
566 	{
567 		(*iter)->setVisible(false);
568 	}
569 	for (std::vector<ToggleTextButton *>::iterator iter = _btnCountries.begin(); iter != _btnCountries.end(); ++iter)
570 	{
571 		(*iter)->setVisible(false);
572 	}
573 	for (std::vector<ToggleTextButton *>::iterator iter = _btnFinances.begin(); iter != _btnFinances.end(); ++iter)
574 	{
575 		(*iter)->setVisible(false);
576 	}
577 
578 	_btnRegionTotal->setVisible(false);
579 	_btnCountryTotal->setVisible(false);
580 	_txtFactor->setVisible(false);
581 }
582 
583 /**
584  * updates the text on the vertical scale
585  * @param lowerLimit minimum value
586  * @param upperLimit maximum value
587  */
updateScale(double lowerLimit,double upperLimit)588 void GraphsState::updateScale(double lowerLimit, double upperLimit)
589 {
590 	double increment = ((upperLimit - lowerLimit) / 9);
591 	if (increment < 10)
592 	{
593 		increment = 10;
594 	}
595 	double text = lowerLimit;
596 	for (int i = 0; i < 10; ++i)
597 	{
598 		_txtScale.at(i)->setText(Text::formatNumber(static_cast<int>(text)));
599 		text += increment;
600 	}
601 }
602 
603 /**
604  * instead of having all our line drawing in one giant ridiculous routine, just use the one we need.
605  */
drawLines()606 void GraphsState::drawLines()
607 {
608 	if (!_country && !_finance)
609 	{
610 		drawRegionLines();
611 	}
612 	else if (!_finance)
613 	{
614 		drawCountryLines();
615 	}
616 	else
617 	{
618 		drawFinanceLines();
619 	}
620 }
621 
622 /**
623  * Sets up the screens and draws the lines for country buttons
624  * to toggle on and off
625  */
drawCountryLines()626 void GraphsState::drawCountryLines()
627 {
628 	//calculate the totals, and set up our upward maximum
629 	int upperLimit = 0;
630 	int lowerLimit = 0;
631 	int totals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
632 	for (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)
633 	{
634 		int total = 0;
635 		if (_alien)
636 		{
637 			for (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)
638 			{
639 				total += _game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry);
640 				if (_game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry) > upperLimit && _countryToggles.at(iter)->_pushed)
641 				{
642 					upperLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityAlien().at(entry);
643 				}
644 			}
645 		}
646 		else if (_income)
647 		{
648 			for (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)
649 			{
650 				total += _game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000;
651 				if (_game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000 > upperLimit && _countryToggles.at(iter)->_pushed)
652 				{
653 					upperLimit = _game->getSavedGame()->getCountries()->at(iter)->getFunding().at(entry) / 1000;
654 				}
655 			}
656 		}
657 		else
658 		{
659 			for (size_t iter = 0; iter != _game->getSavedGame()->getCountries()->size(); ++iter)
660 			{
661 				total += _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);
662 				if (_game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry) > upperLimit && _countryToggles.at(iter)->_pushed)
663 				{
664 					upperLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);
665 				}
666 				if (_game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry) < lowerLimit && _countryToggles.at(iter)->_pushed)
667 				{
668 					lowerLimit = _game->getSavedGame()->getCountries()->at(iter)->getActivityXcom().at(entry);
669 				}
670 
671 			}
672 		}
673 		if (_countryToggles.back()->_pushed && total > upperLimit)
674 			upperLimit = total;
675 	}
676 
677 	//adjust the scale to fit the upward maximum
678 	double range = upperLimit - lowerLimit;
679 	double low = lowerLimit;
680 	int grids = 9; // cells in grid
681 	int check = _income ? 50 : 10;
682 	while (range > check * grids)
683 	{
684 		check *= 2;
685 	}
686 
687 	lowerLimit = 0;
688 	upperLimit = check * grids;
689 
690 	if (low < 0)
691 	{
692 		while (low < lowerLimit)
693 		{
694 			lowerLimit -= check;
695 			// upperLimit -= check;
696 		}
697 	}
698 
699 	range = upperLimit - lowerLimit;
700 	double units = range / 126;
701 
702 	// draw country lines
703 	for (size_t entry = 0; entry != _game->getSavedGame()->getCountries()->size(); ++entry)
704 	{
705 		Country *country = _game->getSavedGame()->getCountries()->at(entry);
706 		_alienCountryLines.at(entry)->clear();
707 		_xcomCountryLines.at(entry)->clear();
708 		_incomeLines.at(entry)->clear();
709 		std::vector<Sint16> newLineVector;
710 		int reduction = 0;
711 		for (size_t iter = 0; iter != 12; ++iter)
712 		{
713 			int x = 312 - (iter*17);
714 			int y = 175 - (-lowerLimit / units);
715 			if (_alien)
716 			{
717 				if (iter < country->getActivityAlien().size())
718 				{
719 					reduction = country->getActivityAlien().at(country->getActivityAlien().size()-(1+iter)) / units;
720 					y -= reduction;
721 					totals[iter] += country->getActivityAlien().at(country->getActivityAlien().size()-(1+iter));
722 				}
723 			}
724 			else if (_income)
725 			{
726 				if (iter < country->getFunding().size())
727 				{
728 					reduction = (country->getFunding().at(country->getFunding().size()-(1+iter)) / 1000) / units;
729 					y -= reduction;
730 					totals[iter] += country->getFunding().at(country->getFunding().size()-(1+iter)) / 1000;
731 				}
732 			}
733 			else
734 			{
735 				if (iter < country->getActivityXcom().size())
736 				{
737 					reduction = country->getActivityXcom().at(country->getActivityXcom().size()-(1+iter)) / units;
738 					y -= reduction;
739 					totals[iter] += country->getActivityXcom().at(country->getActivityXcom().size()-(1+iter));
740 				}
741 			}
742 			if (y >=175)
743 				y = 175;
744 			newLineVector.push_back(y);
745 			int offset = 0;
746 			if (entry % 2)
747 			offset = 8;
748 			if (newLineVector.size() > 1 && _alien)
749 			_alienCountryLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((entry/2)+1)+offset);
750 			else if (newLineVector.size() > 1 && _income)
751 				_incomeLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((entry/2)+1)+offset);
752 			else if (newLineVector.size() > 1)
753 				_xcomCountryLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((entry/2)+1)+offset);
754 			}
755 		if (_alien)
756 			_alienCountryLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);
757 		else if (_income)
758 			_incomeLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);
759 		else
760 			_xcomCountryLines.at(entry)->setVisible(_countryToggles.at(entry)->_pushed);
761 	}
762 	if (_alien)
763 		_alienCountryLines.back()->clear();
764 	else if (_income)
765 		_incomeLines.back()->clear();
766 	else
767 		_xcomCountryLines.back()->clear();
768 
769 	// set up the "total" line
770 	std::vector<Sint16> newLineVector;
771 	for (int iter = 0; iter != 12; ++iter)
772 	{
773 		int x = 312 - (iter*17);
774 		int y = 175 - (-lowerLimit / units);
775 		if (totals[iter] > 0)
776 		{
777 			int reduction = totals[iter] / units;
778 			y -= reduction;
779 		}
780 		newLineVector.push_back(y);
781 		if (newLineVector.size() > 1)
782 		{
783 			if (_alien)
784 				_alienCountryLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset(9));
785 			else if (_income)
786 				_incomeLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset(9));
787 			else
788 				_xcomCountryLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset(9));
789 		}
790 	}
791 	if (_alien)
792 		_alienCountryLines.back()->setVisible(_countryToggles.back()->_pushed);
793 	else if (_income)
794 		_incomeLines.back()->setVisible(_countryToggles.back()->_pushed);
795 	else
796 		_xcomCountryLines.back()->setVisible(_countryToggles.back()->_pushed);
797 	updateScale(lowerLimit, upperLimit);
798 	_txtFactor->setVisible(_income);
799 }
800 
801 /**
802  * Sets up the screens and draws the lines for region buttons
803  * to toggle on and off
804  */
drawRegionLines()805 void GraphsState::drawRegionLines()
806 {
807 	//calculate the totals, and set up our upward maximum
808 	int upperLimit = 0;
809 	int lowerLimit = 0;
810 	int totals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
811 	for (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)
812 	{
813 		int total = 0;
814 		if (_alien)
815 		{
816 			for (size_t iter = 0; iter != _game->getSavedGame()->getRegions()->size(); ++iter)
817 			{
818 				total += _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);
819 				if (_game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry) > upperLimit && _regionToggles.at(iter)->_pushed)
820 				{
821 					upperLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);
822 				}
823 				if (_game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry) < lowerLimit && _regionToggles.at(iter)->_pushed)
824 				{
825 					lowerLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityAlien().at(entry);
826 				}
827 			}
828 		}
829 		else
830 		{
831 			for (size_t iter = 0; iter != _game->getSavedGame()->getRegions()->size(); ++iter)
832 			{
833 				total += _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);
834 				if (_game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry) > upperLimit && _regionToggles.at(iter)->_pushed)
835 				{
836 					upperLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);
837 				}
838 				if (_game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry) < lowerLimit && _regionToggles.at(iter)->_pushed)
839 				{
840 					lowerLimit = _game->getSavedGame()->getRegions()->at(iter)->getActivityXcom().at(entry);
841 				}
842 			}
843 		}
844 		if (_regionToggles.back()->_pushed && total > upperLimit)
845 				upperLimit = total;
846 	}
847 
848 	//adjust the scale to fit the upward maximum
849 	double range = upperLimit - lowerLimit;
850 	double low = lowerLimit;
851 	int check = 10;
852 	while (range > check * 9)
853 	{
854 		check *= 2;
855 	}
856 
857 	lowerLimit = 0;
858 	upperLimit = check * 9;
859 
860 	if (low < 0)
861 	{
862 		while (low < lowerLimit)
863 		{
864 			lowerLimit -= check;
865 			// upperLimit -= check;
866 		}
867 	}
868 	range = upperLimit - lowerLimit;
869 	double units = range / 126;
870 	// draw region lines
871 	for (size_t entry = 0; entry != _game->getSavedGame()->getRegions()->size(); ++entry)
872 	{
873 		Region *region = _game->getSavedGame()->getRegions()->at(entry);
874 		_alienRegionLines.at(entry)->clear();
875 		_xcomRegionLines.at(entry)->clear();
876 		std::vector<Sint16> newLineVector;
877 		int reduction = 0;
878 		for (size_t iter = 0; iter != 12; ++iter)
879 		{
880 			int x = 312 - (iter*17);
881 			int y = 175 - (-lowerLimit / units);
882 			if (_alien)
883 			{
884 				if (iter < region->getActivityAlien().size())
885 				{
886 					reduction = region->getActivityAlien().at(region->getActivityAlien().size()-(1+iter)) / units;
887 					y -= reduction;
888 					totals[iter] += region->getActivityAlien().at(region->getActivityAlien().size()-(1+iter));
889 				}
890 			}
891 			else
892 			{
893 				if (iter < region->getActivityXcom().size())
894 				{
895 					reduction = region->getActivityXcom().at(region->getActivityXcom().size()-(1+iter)) / units;
896 					y -= reduction;
897 					totals[iter] += region->getActivityXcom().at(region->getActivityXcom().size()-(1+iter));
898 				}
899 			}
900 			if (y >=175)
901 				y = 175;
902 			newLineVector.push_back(y);
903 			int offset = 0;
904 			if (entry % 2)
905 				offset = 8;
906 			if (newLineVector.size() > 1 && _alien)
907 				_alienRegionLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((entry/2)+1)+offset);
908 			else if (newLineVector.size() > 1)
909 				_xcomRegionLines.at(entry)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((entry/2)+1)+offset);
910 		}
911 
912 		if (_alien)
913 			_alienRegionLines.at(entry)->setVisible(_regionToggles.at(entry)->_pushed);
914 		else
915 			_xcomRegionLines.at(entry)->setVisible(_regionToggles.at(entry)->_pushed);
916 	}
917 
918 	// set up the "total" line
919 	if (_alien)
920 		_alienRegionLines.back()->clear();
921 	else
922 		_xcomRegionLines.back()->clear();
923 
924 	std::vector<Sint16> newLineVector;
925 	for (int iter = 0; iter != 12; ++iter)
926 	{
927 		int x = 312 - (iter*17);
928 		int y = 175;
929 		if (totals[iter] > 0)
930 		{
931 			int reduction = totals[iter] / units;
932 			y -= reduction;
933 		}
934 		newLineVector.push_back(y);
935 		if (newLineVector.size() > 1)
936 		{
937 			if (_alien)
938 				_alienRegionLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset(9)-8);
939 			else
940 				_xcomRegionLines.back()->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset(9)-8);
941 		}
942 	}
943 	if (_alien)
944 		_alienRegionLines.back()->setVisible(_regionToggles.back()->_pushed);
945 	else
946 		_xcomRegionLines.back()->setVisible(_regionToggles.back()->_pushed);
947 	updateScale(lowerLimit, upperLimit);
948 	_txtFactor->setVisible(false);
949 }
950 
951 /**
952  * Sets up the screens and draws the lines for the finance buttons
953  * to toggle on and off
954  */
drawFinanceLines()955 void GraphsState::drawFinanceLines()
956 {
957 	//set up arrays
958 	int upperLimit = 0;
959 	int lowerLimit = 0;
960 	int incomeTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
961 	int balanceTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
962 	int expendTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
963 	int maintTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
964 	int scoreTotals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
965 	maintTotals[0] = _game->getSavedGame()->getBaseMaintenance() / 1000;
966 
967 	// start filling those arrays with score values
968 	// determine which is the highest one being displayed, so we can adjust the scale
969 	for (size_t entry = 0; entry != _game->getSavedGame()->getFundsList().size(); ++entry)
970 	{
971 		size_t invertedEntry = _game->getSavedGame()->getFundsList().size() - (1 + entry);
972 		maintTotals[entry] += _game->getSavedGame()->getMaintenances().at(invertedEntry) / 1000;
973 		balanceTotals[entry] = _game->getSavedGame()->getFundsList().at(invertedEntry) / 1000;
974 		scoreTotals[entry] = _game->getSavedGame()->getResearchScores().at(invertedEntry);
975 
976 		for (std::vector<Region*>::iterator iter = _game->getSavedGame()->getRegions()->begin(); iter != _game->getSavedGame()->getRegions()->end(); ++iter)
977 		{
978 			scoreTotals[entry] += (*iter)->getActivityXcom().at(invertedEntry) - (*iter)->getActivityAlien().at(invertedEntry);
979 		}
980 
981 		if (_financeToggles.at(2))
982 		{
983 			if (maintTotals[entry] > upperLimit)
984 			{
985 				upperLimit = maintTotals[entry];
986 			}
987 			if (maintTotals[entry] < lowerLimit)
988 			{
989 				lowerLimit = maintTotals[entry];
990 			}
991 		}
992 		if (_financeToggles.at(3))
993 		{
994 			if (balanceTotals[entry] > upperLimit)
995 			{
996 				upperLimit = balanceTotals[entry];
997 			}
998 			if (balanceTotals[entry] < lowerLimit)
999 			{
1000 				lowerLimit = balanceTotals[entry];
1001 			}
1002 		}
1003 		if (_financeToggles.at(4))
1004 		{
1005 			if (scoreTotals[entry] > upperLimit)
1006 			{
1007 				upperLimit = scoreTotals[entry];
1008 			}
1009 			if (scoreTotals[entry] < lowerLimit)
1010 			{
1011 				lowerLimit = scoreTotals[entry];
1012 			}
1013 		}
1014 	}
1015 
1016 	for (size_t entry = 0; entry !=  _game->getSavedGame()->getExpenditures().size(); ++entry)
1017 	{
1018 		expendTotals[entry] = _game->getSavedGame()->getExpenditures().at(_game->getSavedGame()->getExpenditures().size() - (entry + 1)) / 1000;
1019 		incomeTotals[entry] = _game->getSavedGame()->getIncomes().at(_game->getSavedGame()->getIncomes().size() - (entry + 1)) / 1000;
1020 
1021 		if (_financeToggles.at(0) && incomeTotals[entry] > upperLimit)
1022 		{
1023 			upperLimit = incomeTotals[entry];
1024 		}
1025 		if (_financeToggles.at(1) && expendTotals[entry] > upperLimit)
1026 		{
1027 			upperLimit = expendTotals[entry];
1028 		}
1029 	}
1030 
1031 	double range = upperLimit - lowerLimit;
1032 	double low = lowerLimit;
1033 	int check = 250;
1034 	while (range > check * 9)
1035 	{
1036 		check *= 2;
1037 	}
1038 
1039 	lowerLimit = 0;
1040 	upperLimit = check * 9;
1041 
1042 	if (low < 0)
1043 	{
1044 		while (low < lowerLimit)
1045 		{
1046 			lowerLimit -= check;
1047 			// upperLimit -= check;
1048 		}
1049 	}
1050 	//toggle screens
1051 	for (int button = 0; button != 5; ++button)
1052 	{
1053 		_financeLines.at(button)->setVisible(_financeToggles.at(button));
1054 		_financeLines.at(button)->clear();
1055 	}
1056 	range = upperLimit - lowerLimit;
1057 	//figure out how many units to the pixel, then plot the points for the graph and connect the dots.
1058 	double units = range / 126;
1059 	for (int button = 0; button != 5; ++button)
1060 	{
1061 		std::vector<Sint16> newLineVector;
1062 		for (int iter = 0; iter != 12; ++iter)
1063 		{
1064 			int x = 312 - (iter*17);
1065 			int y = 175 - (-lowerLimit / units);
1066 			int reduction = 0;
1067 			switch(button)
1068 			{
1069 			case 0:
1070 				reduction = incomeTotals[iter] / units;
1071 				break;
1072 			case 1:
1073 				reduction = expendTotals[iter] / units;
1074 				break;
1075 			case 2:
1076 				reduction = maintTotals[iter] / units;
1077 				break;
1078 			case 3:
1079 				reduction = balanceTotals[iter] / units;
1080 				break;
1081 			case 4:
1082 				reduction = scoreTotals[iter] / units;
1083 				break;
1084 			}
1085 			y -= reduction;
1086 			newLineVector.push_back(y);
1087 			int offset = button % 2 ? 8 : 0;
1088 			if (newLineVector.size() > 1)
1089 				_financeLines.at(button)->drawLine(x, y, x+17, newLineVector.at(newLineVector.size()-2), Palette::blockOffset((button/2)+1)+offset);
1090 		}
1091 	}
1092 	updateScale(lowerLimit, upperLimit);
1093 	_txtFactor->setVisible(true);
1094 }
1095 
1096 /**
1097  * 'Shift' the buttons to display only GRAPH_MAX_BUTTONS - reset their state from toggles
1098  */
shiftButtons(Action * action)1099 void GraphsState::shiftButtons(Action *action)
1100 {
1101 	// only if active 'screen' is other than finance
1102 	if(_finance)
1103 		return;
1104 	// select the data's we'll processing - regions or countries
1105 	if(_country)
1106 	{
1107 		// too few countries? - return
1108 		if(_countryToggles.size() <= GRAPH_MAX_BUTTONS)
1109 			return;
1110 		else if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)
1111 			scrollButtons(_countryToggles, _btnCountries, _butCountriesOffset, -1);
1112 		else if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)
1113 			scrollButtons(_countryToggles, _btnCountries, _butCountriesOffset, 1);
1114 	}
1115 	else
1116 	{
1117 		// too few regions? - return
1118 		if(_regionToggles.size() <= GRAPH_MAX_BUTTONS)
1119 			return;
1120 		else if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP)
1121 			scrollButtons(_regionToggles, _btnRegions, _butRegionsOffset, -1);
1122 		else if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN)
1123 			scrollButtons(_regionToggles, _btnRegions, _butRegionsOffset, 1);
1124 	}
1125 }
scrollButtons(std::vector<GraphButInfo * > & toggles,std::vector<ToggleTextButton * > & buttons,size_t & offset,int step)1126 void GraphsState::scrollButtons(std::vector<GraphButInfo *> &toggles, std::vector<ToggleTextButton *> &buttons, size_t &offset, int step)
1127 {
1128 	// minus one, 'cause we'll already added the TOTAL button to toggles
1129 	if( int(step + (int)offset) < 0 || offset + step + GRAPH_MAX_BUTTONS >= toggles.size()-1)
1130 		return;
1131 	// set the next offset - cheaper to do it from starters
1132 	offset+=step;
1133 	size_t i=0;
1134 	std::vector<ToggleTextButton *>::iterator iterb=buttons.begin();
1135 	for(std::vector<GraphButInfo *>::iterator itert=toggles.begin(); itert != toggles.end();++itert,++i)
1136 		if(i < offset)
1137 			continue;
1138 		else if(i < offset+GRAPH_MAX_BUTTONS)
1139 			updateButton(*itert,*iterb++);
1140 		else
1141 			return;
1142 }
updateButton(GraphButInfo * from,ToggleTextButton * to)1143 void GraphsState::updateButton(GraphButInfo *from,ToggleTextButton *to)
1144 {
1145 	to->setText(from->_name);
1146 	to->setInvertColor(from->_color);
1147 	to->setPressed(from->_pushed);
1148 }
1149 }
1150