1 /*
2    Copyright (C) 2004 by James Gregory
3    Part of the GalaxyHack project
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License.
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY.
9 
10    See the COPYING file for more details.
11 */
12 
13 
14 #include "Menu_Base.h"
15 #include "Globals.h"
16 #include "RTS.h"
17 
18 #include <boost/filesystem/operations.hpp>
19 
Menu_Base(int ix,int iy,int iParentID,int flags)20 Menu_Base::Menu_Base(int ix, int iy, int iParentID, int flags):
21 GenWindow_Base(ix, iy, iParentID, flags), newItemx(0), newItemy(0), highlight(-1) {}
22 
MouseD(Uint8 button,Uint16 x,Uint16 y)23 bool Menu_Base::MouseD(Uint8 button, Uint16 x, Uint16 y) {
24 	bool ret = GenWindow_Base::MouseD(button, x, y);
25 
26 	if (highlight != -1) {
27 		if (button == SDL_BUTTON_LEFT)
28 			currentSelection.choiceType = MCT_LeftCursor;
29 		else if (button == SDL_BUTTON_RIGHT)
30 			currentSelection.choiceType = MCT_RightCursor;
31 	}
32 
33 	bool derivedInput = SwitchOnChoice(x, y);
34 
35 	if (derivedInput == true)
36 		return derivedInput;
37 	else
38 		return ret;
39 }
40 
MouseM(Uint8 state,Uint16 x,Uint16 y)41 bool Menu_Base::MouseM(Uint8 state, Uint16 x, Uint16 y) {
42 	bool ret = false;
43 	currentSelection.choiceType = MCT_None;
44 	highlight = -1;
45 
46 	//cursor inside window?
47 	if (x >= rect.x
48 	    	&& y >= rect.y
49 	    	&& x < rect.x + rect.w
50 	    	&& y < rect.y + rect.h) {
51 		for (int i = 0; i != items.size(); ++i) {
52 			if (x - rect.x >= items[i].rect.x
53 			        && y - rect.y >= items[i].rect.y
54 			        && x - rect.x < items[i].rect.x + items[i].rect.w
55 			        && y - rect.y < items[i].rect.y + items[i].rect.h) {
56 				//return true even if nothing in particular is highlighted
57 				ret = true;
58 				if (items[i].choice != WC_Nothing) {
59 					highlight = i;
60 
61 					currentSelection.desc = items[i].desc;
62 					currentSelection.choice = items[i].choice;
63 					currentSelection.parem = items[i].parem;
64 
65 					currentSelection.choiceType = MCT_Highlight;
66 					return true;
67 				}
68 			}
69 		}
70 	}
71 
72 	return ret;
73 }
74 
DrawSelf()75 void Menu_Base::DrawSelf() {
76 	GenWindow_Base::DrawSelf();
77 
78 	if (highlight != -1) {
79 		SDL_Rect tempRect;
80 		tempRect.x = items[highlight].rect.x + rect.x;
81 		tempRect.y = items[highlight].rect.y + rect.y;
82 		tempRect.w = items[highlight].rect.w;
83 		tempRect.h = items[highlight].rect.h;
84 
85 		JSDL.BltFill(tempRect, veryDarkGold);
86 	}
87 
88 	for (int i = 0; i != items.size(); ++i) {
89 		int x = items[i].rect.x + rect.x + smallBorderSize;
90 		int y = items[i].rect.y + rect.y + smallBorderSize;
91 
92 		if (items[i].flags & MFLAG_CRECT) {
93 			colorRect.x = x;
94 			colorRect.y = y;
95 			JSDL.BltFill(colorRect, sides[items[i].parem].color);
96 		}
97 
98 		if (items[i].flags & MFLAG_CRECT || items[i].flags & MFLAG_CRECTWIDTH)
99 			x+= colorRect.w + (smallBorderSize << 1);
100 
101 		if (items[i].flags & MFLAG_BOLD) {
102 			int endOfTitle = items[i].desc.find('\n');
103 			string tempStr = items[i].desc.substr(0, endOfTitle - 1);
104 			boldFonts.BlitString(x, y, 0, tempStr);
105 
106 			if (endOfTitle != string::npos) {
107 				tempStr = items[i].desc.substr(endOfTitle, string::npos);
108 				normalFonts.BlitString(x, y, 0, tempStr);
109 			}
110 		} else if (items[i].flags & MFLAG_FADED)
111 			normalFonts.BlitString(x, y, 1, items[i].desc);
112 		else
113 			normalFonts.BlitString(x, y, 0, items[i].desc);
114 	}
115 }
116 
InitRects()117 void Menu_Base::InitRects() {
118 	//width
119 	int longestIndex = 0;
120 	int longest = 0;
121 	rect.h = 0;
122 
123 	for (int i = 0; i != items.size(); ++i) {
124 		int currentLength = 0;
125 
126 		if (items[i].flags & MFLAG_CRECT || items[i].flags & MFLAG_CRECTWIDTH)
127 			currentLength+= colorRect.w + (smallBorderSize << 1);
128 
129 		for (int j = 0; j != items[i].desc.size(); ++j) {
130 			if (items[i].desc[j] != '\n')
131 				++currentLength;
132 			else {
133 				if (currentLength > longest) {
134 					longestIndex = i;
135 					longest = currentLength;
136 				}
137 
138 				currentLength = 0;
139 			}
140 		}
141 
142 		if (currentLength > longest)
143 			longest = currentLength;
144 
145 		rect.h+= items[i].rect.h;
146 	}
147 
148 	int tempLetterWidth;
149 	if (items[longestIndex].flags & MFLAG_BOLD)
150 		tempLetterWidth = boldLetterWidth;
151 	else
152 		tempLetterWidth = normalLetterWidth;
153 
154 	int menuWidth = (longest + 1) * tempLetterWidth;
155 
156 	for (int i = 0; i != items.size(); ++i)
157 		items[i].rect.w = menuWidth;
158 
159 	//overall dimensions
160 	rect.w = menuWidth;
161 
162 	//orientation
163 	if (rect.x > globalSettings.screenWidth * 3 /4)
164 		rect.x-= menuWidth;
165 
166 	if (rect.y > globalSettings.screenHeight >> 1)
167 		rect.y-= items.size() * lineGap;
168 
169 	InitBorder();
170 }
171 
AddItem(MenuItem & tempItem)172 void Menu_Base::AddItem(MenuItem& tempItem) {
173 	tempItem.rect.x = newItemx;
174 	tempItem.rect.y = newItemy;
175 	items.push_back(tempItem);
176 
177 	newItemy += tempItem.rect.h;
178 }
179 
AddBlankItem()180 void Menu_Base::AddBlankItem() {
181 	MenuItem tempItem;
182 	tempItem.choice = WC_Nothing;
183 	AddItem(tempItem);
184 }
185 
186 ///
187 
FileListMenu(int iParentID)188 FileListMenu::FileListMenu(int iParentID):
189 Menu_Base(0, 0, iParentID, 0) {
190 	rect.w = 600;
191 	rect.h = lineGap * 20;
192 
193 	CentreWindow();
194 
195 	rect.y+= lineGap;
196 }
197 
~FileListMenu()198 FileListMenu::~FileListMenu() {
199 	MessageWindows(WC_YouClose, 0, 0, parentID, myID);
200 }
201 
AddDirectory(const string & directory,const string & findExtension,WindowChoice itemChoice)202 void FileListMenu::AddDirectory(const string& directory, const string& findExtension, WindowChoice itemChoice) {
203 	namespace fs = boost::filesystem;
204 
205 	MenuItem tempItem;
206 
207 	fs::directory_iterator directoryEnd; // default construction yields past-the-end
208 	for (fs::directory_iterator iter(directory); iter != directoryEnd; ++iter) {
209 		string filename = iter->path().filename().string();
210 
211 		if (filename.find('.') == filename.npos)
212 			continue;
213 
214 		string fileExtension = filename.substr(filename.find('.'), filename.size() -1);
215 
216 		if (fileExtension != findExtension)
217 			continue;
218 
219 		filename = filename.substr(0, filename.find('.'));
220 
221 		tempItem.desc = filename;
222 		tempItem.choice = itemChoice;
223 		AddItem(tempItem);
224 
225 		if (rect.y + newItemy + tempItem.rect.h > rect.y + rect.h) {
226 			newItemy = 0;
227 			newItemx += menuItemWidth;
228 		}
229 	}
230 }
231 
AddFleets(WindowChoice itemChoice)232 void FileListMenu::AddFleets(WindowChoice itemChoice) {
233 	namespace fs = boost::filesystem;
234 
235 	MenuItem tempItem;
236 
237 	fs::directory_iterator directoryEnd; // default construction yields past-the-end
238 	for (fs::directory_iterator iter(globalSettings.bdp + "fleets/"); iter != directoryEnd; ++iter) {
239 		if (fs::is_directory(*iter)) {
240 			string fleetName = iter->path().filename().string();
241 
242 			if (CheckFleetExists(fleetName)) {
243 				tempItem.desc = fleetName;
244 				tempItem.choice = itemChoice;
245 				AddItem(tempItem);
246 
247 				if (rect.y + newItemy + tempItem.rect.h > rect.y + rect.h) {
248 					newItemy = 0;
249 					newItemx += menuItemWidth;
250 				}
251 			}
252 		}
253 	}
254 }
255 
AddFleetFiles(int whichSide,const string & findExtension,WindowChoice itemChoice)256 void FileListMenu::AddFleetFiles(int whichSide, const string& findExtension, WindowChoice itemChoice) {
257 	namespace fs = boost::filesystem;
258 
259 	MenuItem tempItem;
260 
261 	fs::path iterPath(GetFleetDir(whichSide));
262 	fs::directory_iterator directoryEnd; // default construction yields past-the-end
263 	for (fs::directory_iterator iter(iterPath); iter != directoryEnd; ++iter) {
264 		string filename = iter->path().filename().string();
265 
266 		if (filename.find('.') == filename.npos)
267 			continue;
268 
269 		string beforeDot = filename.substr(0, filename.find('.'));
270 
271 		//it's the main side data file, ignore
272 		if (beforeDot == sides[whichSide].name)
273 			continue;
274 
275 		string fileExtension = filename.substr(filename.find('.'));
276 
277 		if (fileExtension != findExtension)
278 			continue;
279 
280 		tempItem.desc = beforeDot;
281 		tempItem.choice = itemChoice;
282 		AddItem(tempItem);
283 
284 		if (rect.y + newItemy + tempItem.rect.h > rect.y + rect.h) {
285 			newItemy = 0;
286 			newItemx += menuItemWidth;
287 		}
288 	}
289 }
290 
DeleteBox(const string & iFilename,const string & iDirectory,int iParentID)291 DeleteBox::DeleteBox(const string& iFilename, const string& iDirectory, int iParentID):
292 Menu_Base(0, 0, iParentID, 0), filename(iFilename), directory(iDirectory) {
293 	MenuItem tempItem;
294 
295 	tempItem.desc = "Are you sure you wish to delete this file?";
296 	tempItem.choice = WC_Nothing;
297 	AddItem(tempItem);
298 
299 	tempItem.desc = "Yes";
300 	tempItem.choice = WC_Yes;
301 	AddItem(tempItem);
302 
303 	tempItem.desc = "No";
304 	tempItem.choice = WC_No;
305 	AddItem(tempItem);
306 
307 	InitRects();
308 	CentreWindow();
309 }
310 
SwitchOnChoice(Uint16 x,Uint16 y)311 bool DeleteBox::SwitchOnChoice(Uint16 x, Uint16 y) {
312 	if (currentSelection.choiceType == MCT_LeftCursor) {
313 		switch (currentSelection.choice) {
314 		case WC_Yes: {
315 			namespace fs = boost::filesystem;
316 			fs::path tempPath(directory + filename + ".dat");
317 
318 			fs::remove(tempPath);
319 			MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
320 			closed = true;
321 			}
322 			break;
323 
324 		case WC_No:
325 			closed = true;
326 			break;
327 		}
328 	}
329 
330 	return false;
331 }
332 
333 
334