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 #include "DragWindow.h"
14 #include "Globals.h"
15 
16 #include <boost/filesystem/operations.hpp>
17 #include <boost/filesystem/exception.hpp>
18 
DragWindow(int ix,int iy,int iParentID,int flags)19 DragWindow::DragWindow(int ix, int iy, int iParentID, int flags):
20 GenWindow_Base(ix, iy, iParentID, flags), bDrag(0) {}
21 
InitRects()22 void DragWindow::InitRects() {
23 	//shuffle away from edges if we have been created partially off screen
24 	if (rect.x < smallBorderSize)
25 		rect.x = smallBorderSize;
26 	if (rect.y < smallBorderSize)
27 		rect.y = smallBorderSize;
28 	if (rect.x + rect.w + smallBorderSize > globalSettings.screenWidth)
29 		rect.x = globalSettings.screenWidth - rect.w - smallBorderSize;
30 	if (rect.y + rect.h + smallBorderSize > globalSettings.screenHeight)
31 		rect.y = globalSettings.screenHeight - rect.h - smallBorderSize;
32 
33 	InitBorder();
34 
35 	closeRect.x = rect.x + rect.w - genPictures[GENPIC_CLOSEBOX]->w;
36 	closeRect.y = rect.y;
37 	closeRect.w = genPictures[GENPIC_CLOSEBOX]->w;
38 	closeRect.h = genPictures[GENPIC_CLOSEBOX]->h;
39 }
40 
AddSideTitle(int nSide)41 void DragWindow::AddSideTitle(int nSide) {
42 	string outputStr = sides[nSide].name + ":";
43 
44 	theText.push_back(WindowText(outputStr, true));
45 	theText.push_back(WindowText(""));
46 }
47 
AddGroupTitle(int nSide,int nGroup)48 void DragWindow::AddGroupTitle(int nSide, int nGroup) {
49 	char output[32];
50 
51 	sprintf(output, "%s Group %d:", sides[nSide].name.c_str(), nGroup + 1);
52 
53 	theText.push_back(WindowText(output, true));
54 	theText.push_back(WindowText(""));
55 }
56 
DrawSelf()57 void DragWindow::DrawSelf() {
58 	if (visible) {
59 		GenWindow_Base::DrawSelf();
60 
61 		if (!cantClose)
62 			JSDL.Blt(genPictures[GENPIC_CLOSEBOX], closeRect);
63 
64 		int x = rect.x + smallBorderSize;
65 		int y = rect.y + smallBorderSize;
66 
67 		for (int i = 0; i != theText.size(); ++i) {
68 			if (theText[i].bold)
69 				boldFonts.BlitString(x, y, 0, theText[i]);
70 			else
71 				normalFonts.BlitString(x, y, 0, theText[i]);
72 			y+= lineGap;
73 		}
74 	}
75 }
76 
MouseD(Uint8 button,Uint16 x,Uint16 y)77 bool DragWindow::MouseD(Uint8 button, Uint16 x, Uint16 y) {
78 	if (!visible)
79 		return false;
80 
81 	bool ret = GenWindow_Base::MouseD(button, x, y);
82 
83 	if (ret == true) {
84 		if (button == SDL_BUTTON_LEFT) {
85 			//close box?
86 			if (!cantClose
87 		        	&& x >= closeRect.x
88 		        	&& x < closeRect.x + closeRect.w
89 		        	&& y >= closeRect.y
90 		        	&& y < closeRect.y + closeRect.h)
91 				closed = true;
92 			else if (!bStatic) { //start drag
93 				bDrag = true;
94 				saveMousePosx = x;
95 				saveMousePosy = y;
96 			}
97 		}
98 	}
99 
100 	return ret;
101 }
102 
MouseM(Uint8 state,Uint16 x,Uint16 y)103 bool DragWindow::MouseM(Uint8 state, Uint16 x, Uint16 y) {
104 	//drag
105 	if (bDrag && state & SDL_BUTTON(1)) {
106 		int distx = x - saveMousePosx;
107 		int disty = y - saveMousePosy;
108 
109 		Move(distx, disty);
110 
111 		bDrag = true;
112 		saveMousePosx = x;
113 		saveMousePosy = y;
114 		return true;
115 	}
116 
117 	bDrag = false;
118 	return false;
119 }
120 
Move(int distx,int disty)121 void DragWindow::Move(int distx, int disty) {
122 	GenWindow_Base::Move(distx, disty);
123 
124 	closeRect.x+= distx;
125 
126 	closeRect.y+= disty;
127 }
128 
129 
InfoString(const string & iTheString)130 InfoString::InfoString(const string& iTheString):
131 DragWindow(0, 0, none_constant, 0), theString(iTheString) {
132 	//width
133 	int longest = 0;
134 	int currentLength = 0;
135 	int newlines = 0;
136 
137 	for (int i = 0; i != theString.size(); ++i) {
138 		if (theString[i] == '\n') {
139 			if (currentLength > longest)
140 				longest = currentLength;
141 
142 			currentLength = 0;
143 			++newlines;
144 		}
145 		else
146 			++currentLength;
147 	}
148 
149 	//one last time
150 	if (currentLength > longest)
151 		longest = currentLength;
152 
153 	//overall dimensions
154 	rect.w = (longest + 1) * normalLetterWidth;
155 	rect.h = (newlines + 1) * lineGap;
156 
157 	//if just one line, make room for the close cross
158 	if (newlines == 0)
159 		rect.w+= genPictures[GENPIC_CLOSEBOX]->w;
160 
161 	CentreWindow();
162 
163 	InitRects();
164 	anInfoString = 1;
165 }
166 
~InfoString()167 InfoString::~InfoString() {
168 	anInfoString = 0;
169 }
170 
DrawSelf()171 void InfoString::DrawSelf() {
172 	DragWindow::DrawSelf();
173 
174 	int x = rect.x + smallBorderSize;
175 	int y = rect.y + smallBorderSize;
176 
177 
178 	normalFonts.BlitString(x, y, 0, theString);
179 }
180 
181 ///
182 
183 
Slider(int ix,int iy,int iSliderVar,int iVarMin,int iVarMax,int iParentID,int flags)184 Slider::Slider(int ix, int iy, int iSliderVar, int iVarMin, int iVarMax, int iParentID, int flags):
185 DragWindow(ix, iy, iParentID, flags), varPointer(&sliderVar), sliderVar(iSliderVar) {
186 	Init(iVarMin, iVarMax);
187 }
188 
Slider(int ix,int iy,int * iVarPointer,int iVarMin,int iVarMax,int iParentID,int flags)189 Slider::Slider(int ix, int iy, int* iVarPointer, int iVarMin, int iVarMax, int iParentID, int flags):
190 DragWindow(ix, iy, iParentID, flags), varPointer(iVarPointer) {
191 	Init(iVarMin, iVarMax);
192 }
193 
Init(int iVarMin,int iVarMax)194 void Slider::Init(int iVarMin, int iVarMax) {
195 	shadowVar = *varPointer;
196 	bSliderDrag = 0;
197 	varMin = iVarMin;
198 	varMax = iVarMax;
199 
200 	rect.w = sliderWinWidth;
201 	rect.h = sliderWinHeight;
202 	InitRects();
203 
204 	ruleLength = rect.w - (lineGap << 1);
205 
206 	middle = rect.y + (rect.h >> 1) + (lineGap >> 1);
207 }
208 
MouseD(Uint8 button,Uint16 x,Uint16 y)209 bool Slider::MouseD(Uint8 button, Uint16 x, Uint16 y) {
210 	//note not DragWindow::MouseD
211 	bool ret = GenWindow_Base::MouseD(button, x, y);
212 
213 	//slider start drag?
214 	if (button == SDL_BUTTON_LEFT
215 	         && x > sliderRect.x
216 	         && x < sliderRect.x + sliderRect.w
217 	         && y > sliderRect.y
218 	         && y < sliderRect.y + sliderRect.h) {
219 		bSliderDrag = true;
220 		saveMousePosx = x;
221 	} else
222 		//check for the window start drag
223 		ret = DragWindow::MouseD(button, x, y);
224 
225 	return ret;
226 }
227 
MouseM(Uint8 state,Uint16 x,Uint16 y)228 bool Slider::MouseM(Uint8 state, Uint16 x, Uint16 y) {
229 	bool ret = false;
230 
231 	//slider drag
232 	if (bSliderDrag && state & SDL_BUTTON(1)) {
233 		int dPos = x - saveMousePosx;
234 		sliderRect.x+= dPos;
235 
236 		//add to the value
237 		shadowVar += dPos * (varMax - varMin) / ruleLength;
238 
239 		if (shadowVar > varMax)
240 			shadowVar = varMax;
241 		else if (shadowVar < varMin)
242 			shadowVar = varMin;
243 
244 		*varPointer = static_cast<int>(shadowVar);
245 
246 		bSliderDrag = true;
247 		saveMousePosx = x;
248 		ret = true;
249 	} else {
250 		bSliderDrag = false;
251 		ret = DragWindow::MouseM(state, x, y);
252 	}
253 
254 	//work out middle /after/ any dragging of us or a parent
255 	middle = rect.y + (rect.h >> 1) + (lineGap >> 1);
256 
257 	return ret;
258 }
259 
DrawSelf()260 void Slider::DrawSelf() {
261 	DragWindow::DrawSelf();
262 
263 	//draw a line down the centre
264 	SDL_Rect tempRect;
265 
266 	tempRect.x = rect.x + lineGap;
267 	tempRect.y = middle;
268 	tempRect.w = static_cast<Uint16>(ruleLength);
269 	tempRect.h = smallBorderSize;
270 
271 	JSDL.BltFill(tempRect,veryDarkGold);
272 
273 	//we have to rework out position each time because something
274 	//other than us might have changed it
275 	//strange ordering to avoid casting, theVar/varMax * ruleLength makes more sense
276 	int leftPos = rect.x + lineGap + (ruleLength * (*varPointer - varMin) / (varMax - varMin));
277 	sliderRect.x = leftPos;
278 	sliderRect.y = middle - (sliderHeight >> 1);
279 	sliderRect.w = sliderWidth;
280 	sliderRect.h = sliderHeight;
281 
282 	JSDL.BltFill(sliderRect, gold);
283 }
284 
285 
SliderWithUnits(int ix,int iy,int iSliderVar,int iVarMin,int iVarMax,const string & iVarName,const string & iVarUnits,int iParentID,int flags)286 SliderWithUnits::SliderWithUnits(int ix, int iy, int iSliderVar, int iVarMin, int iVarMax, const string& iVarName, const string& iVarUnits, int iParentID, int flags):
287 Slider(ix, iy, iSliderVar, iVarMin, iVarMax, iParentID, flags), varName(iVarName), varUnits(iVarUnits) {}
288 
SliderWithUnits(int ix,int iy,int * iVarPointer,int iVarMin,int iVarMax,const string & iVarName,const string & iVarUnits,int iParentID,int flags)289 SliderWithUnits::SliderWithUnits(int ix, int iy, int* iVarPointer, int iVarMin, int iVarMax, const string& iVarName, const string& iVarUnits, int iParentID, int flags):
290 Slider(ix, iy, iVarPointer, iVarMin, iVarMax, iParentID, flags), varName(iVarName), varUnits(iVarUnits) {}
291 
DrawSelf()292 void SliderWithUnits::DrawSelf() {
293 	Slider::DrawSelf();
294 
295 	//in text
296 	int x = rect.x + smallBorderSize;
297 	int y = rect.y + smallBorderSize;
298 	char output[48];
299 	sprintf(output, "%s: %d %s", varName.c_str(), *varPointer, varUnits.c_str());
300 	normalFonts.BlitString(x, y, 0, output);
301 }
302 
DrawSelf()303 void StringInputBox::DrawSelf() {
304 	DragWindow::DrawSelf();
305 
306 	int x = rect.x + bigBorderSize;
307 	int y = rect.y + lineGap;
308 	normalFonts.BlitString(x, y, 0, title);
309 
310 	x+= lineGap;
311 	y+= lineGap;
312 
313 	normalFonts.BlitString(x, y, 0, theInput);
314 }
315 
Keyboard(SDL_keysym & keysym)316 bool StringInputBox::Keyboard(SDL_keysym& keysym) {
317 	switch (StringInput(keysym, theInput, maxTextInputLength)) {
318 	//user escaped
319 	case -1:
320 		closed = true;
321 		break;
322 
323 	//user hit enter
324 	case 0:
325 		userHitEnter = 1;
326 		closed = true;
327 		break;
328 
329 	//keep going
330 	case 1:
331 		break;
332 	}
333 
334 	return true;
335 }
336 
CopyBox(const string & iOldName,const string & iDirectory,int iParentID)337 CopyBox::CopyBox(const string& iOldName, const string& iDirectory, int iParentID):
338 StringInputBox(maxNameLength, iParentID, 0), oldName(iOldName), directoryName(iDirectory) {
339 	title = "What would you like to call the copy?";
340 	rect.x = 200;
341 	rect.y = 200;
342 	rect.w = 400;
343 	rect.h = 100;
344 
345 	InitRects();
346 }
347 
Keyboard(SDL_keysym & keysym)348 bool CopyBox::Keyboard(SDL_keysym& keysym) {
349 	StringInputBox::Keyboard(keysym);
350 
351 	namespace fs = boost::filesystem;
352 
353 	if (userHitEnter) {
354 		try {
355 			fs::path sourcePath(directoryName + oldName + ".dat");
356 			fs::path destPath(directoryName + theInput + ".dat");
357 
358 			fs::copy_file(sourcePath, destPath);
359 			MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
360 		} catch (fs::filesystem_error e) {
361 			string errorStr = "\n";
362 			errorStr += e.what();
363 			CreateInfoString(errorStr);
364 		}
365 	}
366 
367 	return true;
368 }
369 
370 
LargeBlankDW(const string & iTitle)371 LargeBlankDW::LargeBlankDW(const string& iTitle):
372 DragWindow(0, 0, none_constant, 0) {
373 	rect.w = 600;
374 	rect.h = lineGap * 22;
375 
376 	CentreWindow();
377 	InitRects();
378 
379 	theText.push_back(WindowText(iTitle, true));
380 }
381 
382