1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 /** ****************************************************************************
11 *** \file    shop_leave.cpp
12 *** \author  Tyler Olsen, roots@allacrost.org
13 *** \brief   Source file for leave interface of shop mode
14 ***
15 *** \note The contents of this file are near identical to the contents of
16 *** shop_confirm.cpp. When making any changes to this file, please look to
17 *** shop_confirm.cpp to see if it should have similar changes made.
18 *** ***************************************************************************/
19 
20 #include "defs.h"
21 #include "utils.h"
22 
23 #include "audio.h"
24 #include "input.h"
25 #include "system.h"
26 #include "video.h"
27 #include "mode_manager.h"
28 
29 #include "shop.h"
30 #include "shop_leave.h"
31 #include "shop_buy.h"
32 #include "shop_sell.h"
33 #include "shop_trade.h"
34 
35 using namespace std;
36 
37 using namespace hoa_utils;
38 using namespace hoa_audio;
39 using namespace hoa_input;
40 using namespace hoa_system;
41 using namespace hoa_video;
42 using namespace hoa_gui;
43 using namespace hoa_mode_manager;
44 
45 namespace hoa_shop {
46 
47 namespace private_shop {
48 
49 // *****************************************************************************
50 // ***** LeaveInterface class methods
51 // *****************************************************************************
52 
LeaveInterface()53 LeaveInterface::LeaveInterface() :
54 	_state(LEAVE_STATE_MAIN),
55 	_active_list(ACTIVE_LIST_BUY),
56 	_buy_count(0),
57 	_buy_unique(0),
58 	_sell_count(0),
59 	_sell_unique(0),
60 	_trade_count(0),
61 	_trade_characters(0),
62 	_buy_list_display(NULL),
63 	_sell_list_display(NULL)
64 {
65 	TextStyle stats_style("text20");
66 
67 	_buy_header.SetStyle(TextStyle("title22", Color::white));
68 	_buy_header.SetText(UTranslate("Purchases"));
69 	_buy_stats.SetStyle(stats_style);
70 
71 	_sell_header.SetStyle(TextStyle("title22", Color::white));
72 	_sell_header.SetText(UTranslate("Sales"));
73 	_sell_stats.SetStyle(stats_style);
74 
75 	_trade_header.SetStyle(TextStyle("title22", Color::white));
76 	_trade_header.SetText(UTranslate("Trades"));
77 	_trade_stats.SetStyle(stats_style);
78 
79 	_name_header.SetStyle(TextStyle("title24"));
80 	_name_header.SetText(UTranslate("Name"));
81 
82 	_properties_header.SetOwner(ShopMode::CurrentInstance()->GetMiddleWindow());
83 	_properties_header.SetPosition(480.0f, 390.0f);
84 	_properties_header.SetDimensions(300.0f, 30.0f, 4, 1, 4, 1);
85 	_properties_header.SetOptionAlignment(VIDEO_X_RIGHT, VIDEO_Y_CENTER);
86 	_properties_header.SetTextStyle(TextStyle("title24"));
87 	_properties_header.SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
88 	_properties_header.AddOption(UTranslate("Price"));
89 	_properties_header.AddOption(UTranslate("Stock"));
90 	_properties_header.AddOption(UTranslate("Own"));
91 	_properties_header.AddOption(MakeUnicodeString(""));
92 
93 	_empty_list_text.SetStyle(TextStyle("text24"));
94 	_empty_list_text.SetText(UTranslate("No marked transactions."));
95 
96 	_buy_list_display = new BuyListDisplay();
97 	_sell_list_display = new SellListDisplay();
98 
99 	_main_prompt.SetStyle(TextStyle("text24"));
100 	_main_prompt.SetText(UTranslate("Your order is not yet final. Are you sure you want to leave the shop?"));
101 	_main_actions.SetOwner(ShopMode::CurrentInstance()->GetBottomWindow());
102 	_main_actions.SetPosition(60.0f, 80.0f);
103 	_main_actions.SetDimensions(600.0f, 40.0f, 3, 1, 3, 1);
104 	_main_actions.SetOptionAlignment(VIDEO_X_LEFT, VIDEO_Y_CENTER);
105 	_main_actions.SetTextStyle(TextStyle("title24"));
106 	_main_actions.SetCursorState(VIDEO_CURSOR_STATE_VISIBLE);
107 	_main_actions.SetCursorOffset(-55.0f, 30.0f);
108 	_main_actions.SetHorizontalWrapMode(VIDEO_WRAP_MODE_NONE);
109 	_main_actions.AddOption(UTranslate("View Order"));
110 	_main_actions.AddOption(UTranslate("Confirm Order"));
111 	_main_actions.AddOption(UTranslate("Leave Shop"));
112 	_main_actions.SetSelection(0);
113 }
114 
115 
116 
~LeaveInterface()117 LeaveInterface::~LeaveInterface() {
118 	if (_buy_list_display != NULL)
119 		delete _buy_list_display;
120 	if (_sell_list_display != NULL)
121 		delete _sell_list_display;
122 
123 	_buy_list_display = NULL;
124 	_sell_list_display = NULL;
125 }
126 
127 
128 
MakeActive()129 void LeaveInterface::MakeActive() {
130 	map<uint32, ShopObject*>* buy_list = ShopMode::CurrentInstance()->GetBuyList();
131 	map<uint32, ShopObject*>* sell_list = ShopMode::CurrentInstance()->GetSellList();
132 	// TODO: Get a container of all trades
133 
134 	// Vector constructs required by the BuyListDisplay/SellListDisplay classes
135 	vector<ShopObject*> buy_vector;
136 	vector<ShopObject*> sell_vector;
137 
138 	buy_vector.reserve(buy_list->size());
139 	sell_vector.reserve(sell_list->size());
140 
141 	_buy_count = 0;
142 	_buy_unique = 0;
143 	for (map<uint32, ShopObject*>::iterator i = buy_list->begin(); i != buy_list->end(); i++) {
144 		_buy_unique++;
145 		_buy_count += i->second->GetBuyCount();
146 		buy_vector.push_back(i->second);
147 	}
148 
149 	_sell_count = 0;
150 	_sell_unique = 0;
151 	for (map<uint32, ShopObject*>::iterator i = sell_list->begin(); i != sell_list->end(); i++) {
152 		_sell_unique++;
153 		_sell_count += i->second->GetSellCount();
154 		sell_vector.push_back(i->second);
155 	}
156 
157 	_trade_count = 0;
158 	_trade_characters = 0;
159 	// TODO: Iterate through the trade container similar to buy and sell containers
160 
161 	_buy_list_display->PopulateList(buy_vector);
162 	_sell_list_display->PopulateList(sell_vector);
163 
164 	// Determine which active list should be initially shown and change properties as needed
165 	if (_buy_count != 0) {
166 		_active_list = ACTIVE_LIST_BUY;
167 		_buy_header.SetStyle(TextStyle("title24", Color::yellow));
168 		_sell_header.SetStyle(TextStyle("title22", Color::white));
169 		_trade_header.SetStyle(TextStyle("title22", Color::white));
170 		_properties_header.SetOptionText(3, UTranslate("Buy"));
171 	}
172 	else if (_sell_count != 0) {
173 		_active_list = ACTIVE_LIST_SELL;
174 		_buy_header.SetStyle(TextStyle("title22", Color::white));
175 		_sell_header.SetStyle(TextStyle("title24", Color::yellow));
176 		_trade_header.SetStyle(TextStyle("title22", Color::white));
177 		_properties_header.SetOptionText(3, UTranslate("Sell"));
178 	}
179 	else if (_trade_count != 0) {
180 		_active_list = ACTIVE_LIST_TRADE;
181 		_buy_header.SetStyle(TextStyle("title22", Color::white));
182 		_sell_header.SetStyle(TextStyle("title22", Color::white));
183 		_trade_header.SetStyle(TextStyle("title24", Color::yellow));
184 	}
185 	else {
186 		_active_list = ACTIVE_LIST_BUY;
187 		_buy_header.SetStyle(TextStyle("title24", Color::yellow));
188 		_sell_header.SetStyle(TextStyle("title22", Color::white));
189 		_trade_header.SetStyle(TextStyle("title22", Color::white));
190 		_properties_header.SetOptionText(3, UTranslate("Buy"));
191 	}
192 
193 	_buy_stats.SetText(NumberToString(_buy_count) + Translate(" count") + "\n" +
194 		NumberToString(_buy_unique) + Translate(" unique"));
195 	_sell_stats.SetText(NumberToString(_sell_count) + Translate(" count") + "\n" +
196 		NumberToString(_sell_unique) + Translate(" unique"));
197 	_trade_stats.SetText(NumberToString(_trade_count) + Translate(" count") + "\n" +
198 		NumberToString(_trade_characters) + Translate(" characters"));
199 
200 	_state = LEAVE_STATE_MAIN;
201 	_main_actions.SetSelection(0);
202 
203 	_main_actions.SetCursorState(VIDEO_CURSOR_STATE_VISIBLE);
204 	_buy_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
205 	_sell_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
206 
207 	ShopMode::CurrentInstance()->ObjectViewer()->SetSelectedObject(NULL);
208 	ShopMode::CurrentInstance()->ObjectViewer()->ChangeViewMode(SHOP_VIEW_MODE_INFO);
209 } // void LeaveInterface::MakeActive()
210 
211 
212 
Update()213 void LeaveInterface::Update() {
214 	_main_actions.Update();
215 	_buy_list_display->Update();
216 	_sell_list_display->Update();
217 
218 	// A swap press changes the active transaction list being shown. It takes precedence over all other
219 	// input events. Only the "info" state ignores this command because the transaction list is not visible
220 	// while in this state
221 	if ((InputManager->SwapPress()) && (_state != LEAVE_STATE_INFO)) {
222 		_CycleActiveTransactionList();
223 		return;
224 	}
225 
226 	if (_state == LEAVE_STATE_MAIN) {
227 		if (InputManager->CancelPress()) {
228 			ShopMode::CurrentInstance()->ChangeState(SHOP_STATE_ROOT);
229 			return;
230 		}
231 
232 		else if (InputManager->ConfirmPress()) {
233 			switch (_main_actions.GetSelection()) {
234 				case 0: // "View Order"
235 					_ChangeState(LEAVE_STATE_LIST);
236 					return;
237 				case 1: // "Confirm Order"
238 					ShopMode::CurrentInstance()->ChangeState(SHOP_STATE_CONFIRM);
239 					return;
240 				case 2: // "Leave Shop"
241 					ModeManager->Pop();
242 					return;
243 				default:
244 					IF_PRINT_WARNING(SHOP_DEBUG) << "invalid selection in primary action options: "
245 						<< _main_actions.GetSelection() << endl;
246 					return;
247 			}
248 		}
249 
250 		else if (InputManager->LeftPress()) {
251 			_main_actions.InputLeft();
252 		}
253 		else if (InputManager->RightPress()) {
254 			_main_actions.InputRight();
255 		}
256 	}
257 
258 	else if (_state == LEAVE_STATE_LIST) {
259 		if (InputManager->CancelPress()) {
260 			_ChangeState(LEAVE_STATE_MAIN);
261 			return;
262 		}
263 
264 		switch (_active_list) {
265 			case ACTIVE_LIST_BUY:
266 				if (InputManager->ConfirmPress()) {
267 					_ChangeState(LEAVE_STATE_INFO);
268 				}
269 				else if (InputManager->UpPress()) {
270 					_buy_list_display->InputUp();
271 				}
272 				else if (InputManager->DownPress()) {
273 					_buy_list_display->InputDown();
274 				}
275 				return;
276 			case ACTIVE_LIST_SELL:
277 				if (InputManager->ConfirmPress()) {
278 					_ChangeState(LEAVE_STATE_INFO);
279 				}
280 				else if (InputManager->UpPress()) {
281 					_sell_list_display->InputUp();
282 				}
283 				else if (InputManager->DownPress()) {
284 					_sell_list_display->InputDown();
285 				}
286 				return;
287 			case ACTIVE_LIST_TRADE:
288 				// TODO
289 				return;
290 			default:
291 				IF_PRINT_WARNING(SHOP_DEBUG) << "invalid transaction list was active: "
292 					<< _active_list << endl;
293 				return;
294 		}
295 	}
296 
297 	else if (_state == LEAVE_STATE_INFO) {
298 		if (InputManager->ConfirmPress() || InputManager->CancelPress()) {
299 			_ChangeState(LEAVE_STATE_LIST);
300 			return;
301 		}
302 	}
303 
304 	else {
305 		IF_PRINT_WARNING(SHOP_DEBUG) << "invalid leave state was active: " << _state << endl;
306 		_state = LEAVE_STATE_MAIN;
307 	}
308 } // void LeaveInterface::Update()
309 
310 
311 
Draw()312 void LeaveInterface::Draw() {
313 	// Draw the contents of the middle window. Either selected object information or the active transaction list
314 	if (_state == LEAVE_STATE_INFO) {
315 		ShopMode::CurrentInstance()->ObjectViewer()->Draw();
316 	}
317 	else {
318 		// Draw the transaction type headers and stats
319 		VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, 0);
320 		VideoManager->Move(140.0f, 525.0f);
321 		_buy_header.Draw();
322 		VideoManager->SetDrawFlags(VIDEO_Y_TOP, 0);
323 		_buy_stats.Draw();
324 
325 		VideoManager->SetDrawFlags(VIDEO_Y_BOTTOM, 0);
326 		VideoManager->MoveRelative(0.0f, -105.0f);
327 		_sell_header.Draw();
328 		VideoManager->SetDrawFlags(VIDEO_Y_TOP, 0);
329 		_sell_stats.Draw();
330 
331 		VideoManager->SetDrawFlags(VIDEO_Y_BOTTOM, 0);
332 		VideoManager->MoveRelative(0.0f, -105.0f);
333 		_trade_header.Draw();
334 		VideoManager->SetDrawFlags(VIDEO_Y_TOP, 0);
335 		_trade_stats.Draw();
336 
337 		// Draw the list headers and contents
338 		if ((_active_list == ACTIVE_LIST_BUY) && (_buy_list_display->IsListEmpty() == false)) {
339 			VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, 0);
340 			VideoManager->Move(295.0f, 558.0f);
341 			_name_header.Draw();
342 
343 			_properties_header.Draw();
344 			_buy_list_display->Draw();
345 		}
346 		else if ((_active_list == ACTIVE_LIST_SELL) && (_sell_list_display->IsListEmpty() == false)) {
347 			VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, 0);
348 			VideoManager->Move(295.0f, 558.0f);
349 			_name_header.Draw();
350 
351 			_properties_header.Draw();
352 			_sell_list_display->Draw();
353 		}
354 		else if ((_active_list == ACTIVE_LIST_TRADE) && (_trade_count != 0)) {
355 			// TODO: once trade support is added, change above condition `(_trade_count != 0)`
356 			// to a check on the trade list display's empty status
357 		}
358 		else { // The active list is empty
359 			VideoManager->SetDrawFlags(VIDEO_X_CENTER, VIDEO_Y_CENTER, 0);
360 			VideoManager->Move(560.0f, 405.0f);
361 			_empty_list_text.Draw();
362 		}
363 	}
364 
365 	// Draw the contents of the lower window, the main prompt and actions
366 	VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_CENTER, 0);
367 	VideoManager->Move(160.0f, 180.0f);
368 	_main_prompt.Draw();
369 	_main_actions.Draw();
370 } // void LeaveInterface::Draw()
371 
372 
373 
_ChangeState(LEAVE_STATE new_state)374 void LeaveInterface::_ChangeState(LEAVE_STATE new_state) {
375 	if (_state == new_state) {
376 		IF_PRINT_WARNING(SHOP_DEBUG) << "new state was the same as the current state: " << _state << endl;
377 		return;
378 	}
379 
380 	// Modify appropriate display properties of former state
381 	if (_state == LEAVE_STATE_MAIN) {
382 		_main_actions.SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
383 	}
384 	else if (_state == LEAVE_STATE_LIST) {
385 		_buy_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
386 		_sell_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_HIDDEN);
387 	}
388 	else if (_state == LEAVE_STATE_INFO) {
389 		ShopMode::CurrentInstance()->ObjectViewer()->SetSelectedObject(NULL);
390 	}
391 
392 	// Modify appropriate display properties of new state
393 	if (new_state == LEAVE_STATE_MAIN) {
394 		_main_actions.SetCursorState(VIDEO_CURSOR_STATE_VISIBLE);
395 	}
396 	else if (new_state == LEAVE_STATE_LIST) {
397 		_buy_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_VISIBLE);
398 		_sell_list_display->GetIdentifyList().SetCursorState(VIDEO_CURSOR_STATE_VISIBLE);
399 	}
400 	else if (new_state == LEAVE_STATE_INFO) {
401 		ShopObject* selected_object = NULL;
402 		switch (_active_list) {
403 			case ACTIVE_LIST_BUY:
404 				selected_object = _buy_list_display->GetSelectedObject();
405 				break;
406 			case ACTIVE_LIST_SELL:
407 				selected_object = _sell_list_display->GetSelectedObject();
408 				break;
409 			case ACTIVE_LIST_TRADE:
410 				// TODO: implement once trade interface is complete
411 				break;
412 			default:
413 				IF_PRINT_WARNING(SHOP_DEBUG) << "invalid transaction list was active: " << _active_list << endl;
414 				break;
415 		}
416 		ShopMode::CurrentInstance()->ObjectViewer()->SetSelectedObject(selected_object);
417 	}
418 	_state = new_state;
419 } // void LeaveInterface::_ChangeState(LEAVE_STATE new_state)
420 
421 
422 
_CycleActiveTransactionList()423 void LeaveInterface::_CycleActiveTransactionList() {
424 	TextStyle highlight("title24", Color::yellow);
425 	TextStyle standard("title22", Color::white);
426 
427 	if (_active_list == ACTIVE_LIST_BUY) {
428 		_active_list = ACTIVE_LIST_SELL;
429 		_buy_header.SetStyle(standard);
430 		_sell_header.SetStyle(highlight);
431 		_properties_header.SetOptionText(3, UTranslate("Sell"));
432 	}
433 	else if (_active_list == ACTIVE_LIST_SELL) {
434 		_active_list = ACTIVE_LIST_TRADE;
435 		_sell_header.SetStyle(standard);
436 		_trade_header.SetStyle(highlight);
437 	}
438 	else if (_active_list == ACTIVE_LIST_TRADE) {
439 		_active_list = ACTIVE_LIST_BUY;
440 		_trade_header.SetStyle(standard);
441 		_buy_header.SetStyle(highlight);
442 		_properties_header.SetOptionText(3, UTranslate("Buy"));
443 	}
444 	else {
445 		IF_PRINT_WARNING(SHOP_DEBUG) << "invalid transaction list was active: " << _active_list << endl;
446 	}
447 }
448 
449 } // namespace private_shop
450 
451 } // namespace hoa_shop
452