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