1 /***************************************************************************
2 * Mechanized Assault and Exploration Reloaded Projectfile *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 #include "ui/graphical/menu/widgets/pushbutton.h"
21
22 #include "ui/graphical/application.h"
23
24 #include "settings.h"
25 #include "video.h"
26 #include "unifonts.h"
27 #include "main.h"
28 #include "input/mouse/mouse.h"
29 #include "output/sound/sounddevice.h"
30 #include "output/sound/soundchannel.h"
31 #include "utility/drawing.h"
32
33 //------------------------------------------------------------------------------
cPushButton(const cBox<cPosition> & area)34 cPushButton::cPushButton (const cBox<cPosition>& area) :
35 cClickableWidget (area),
36 buttonType (ePushButtonType::Invisible),
37 fontType (FONT_LATIN_BIG),
38 text (""),
39 clickSound (&SoundData.SNDHudButton),
40 isLocked (false)
41
42 {
43 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
44 fontType = FONT_LATIN_SMALL_WHITE;
45 renewSurface();
46 }
47
48 //------------------------------------------------------------------------------
cPushButton(const cPosition & position,ePushButtonType buttonType_)49 cPushButton::cPushButton (const cPosition& position, ePushButtonType buttonType_) :
50 cClickableWidget (position),
51 buttonType (buttonType_),
52 fontType (FONT_LATIN_BIG),
53 text (""),
54 clickSound (&SoundData.SNDHudButton),
55 isLocked (false)
56 {
57 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
58 fontType = FONT_LATIN_SMALL_WHITE;
59 renewSurface();
60 }
61
62 //------------------------------------------------------------------------------
cPushButton(const cPosition & position,ePushButtonType buttonType_,cSoundChunk * clickSound_)63 cPushButton::cPushButton (const cPosition& position, ePushButtonType buttonType_, cSoundChunk* clickSound_) :
64 cClickableWidget (position),
65 buttonType (buttonType_),
66 fontType (FONT_LATIN_BIG),
67 text (""),
68 clickSound (clickSound_),
69 isLocked (false)
70 {
71 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
72 fontType = FONT_LATIN_SMALL_WHITE;
73 renewSurface();
74 }
75
76 //------------------------------------------------------------------------------
cPushButton(const cPosition & position,ePushButtonType buttonType_,const std::string & text_,eUnicodeFontType fontType_)77 cPushButton::cPushButton (const cPosition& position, ePushButtonType buttonType_, const std::string& text_, eUnicodeFontType fontType_) :
78 cClickableWidget (position),
79 buttonType (buttonType_),
80 fontType (fontType_),
81 text (text_),
82 clickSound (&SoundData.SNDHudButton),
83 isLocked (false)
84 {
85 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
86 fontType = FONT_LATIN_SMALL_WHITE;
87 renewSurface();
88 }
89
90 //------------------------------------------------------------------------------
cPushButton(const cPosition & position,ePushButtonType buttonType_,cSoundChunk * clickSound_,const std::string & text_,eUnicodeFontType fontType_)91 cPushButton::cPushButton (const cPosition& position, ePushButtonType buttonType_, cSoundChunk* clickSound_, const std::string& text_, eUnicodeFontType fontType_) :
92 cClickableWidget (position),
93 buttonType (buttonType_),
94 fontType (fontType_),
95 text (text_),
96 clickSound (clickSound_),
97 isLocked (false)
98 {
99 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
100 fontType = FONT_LATIN_SMALL_WHITE;
101 renewSurface();
102 }
103
104 //------------------------------------------------------------------------------
draw(SDL_Surface & destination,const cBox<cPosition> & clipRect)105 void cPushButton::draw (SDL_Surface& destination, const cBox<cPosition>& clipRect)
106 {
107 SDL_Rect position = getArea().toSdlRect();
108 if (surface != nullptr) SDL_BlitSurface (surface.get(), nullptr, &destination, &position);
109
110 if (!text.empty())
111 {
112 if (buttonType >= ePushButtonType::HudNext && buttonType <= ePushButtonType::HudFiles)
113 {
114 if (isPressed || isLocked) font->showTextCentered (position.x + position.w / 2, position.y + getTextYOffset(), text, FONT_LATIN_SMALL_GREEN);
115 else font->showTextCentered (position.x + position.w / 2, position.y + getTextYOffset() - 1, text, FONT_LATIN_SMALL_RED);
116 font->showTextCentered (position.x + position.w / 2 - 1, position.y + getTextYOffset() - 1 + (isPressed || isLocked ? 1 : 0), text, FONT_LATIN_SMALL_WHITE);
117 }
118 else font->showTextCentered (position.x + position.w / 2, position.y + getTextYOffset(), text, fontType);
119 }
120
121 cWidget::draw (destination, clipRect);
122 }
123
124 //------------------------------------------------------------------------------
handleMousePressed(cApplication & application,cMouse & mouse,eMouseButtonType button)125 bool cPushButton::handleMousePressed (cApplication& application, cMouse& mouse, eMouseButtonType button)
126 {
127 if (isLocked) return false;
128 return cClickableWidget::handleMousePressed (application, mouse, button);
129 }
130
131 //------------------------------------------------------------------------------
handleMouseReleased(cApplication & application,cMouse & mouse,eMouseButtonType button)132 bool cPushButton::handleMouseReleased (cApplication& application, cMouse& mouse, eMouseButtonType button)
133 {
134 if (isLocked)
135 {
136 cClickableWidget::finishMousePressed (application, mouse, button);
137 return false;
138 }
139 return cClickableWidget::handleMouseReleased (application, mouse, button);
140 }
141
142 //------------------------------------------------------------------------------
handleClicked(cApplication & application,cMouse & mouse,eMouseButtonType button)143 bool cPushButton::handleClicked (cApplication& application, cMouse& mouse, eMouseButtonType button)
144 {
145 if (button == eMouseButtonType::Left)
146 {
147 if (clickSound) cSoundDevice::getInstance().playSoundEffect (*clickSound);
148 clicked();
149 return true;
150 }
151 return false;
152 }
153
154 //------------------------------------------------------------------------------
setPressed(bool pressed)155 void cPushButton::setPressed (bool pressed)
156 {
157 cClickableWidget::setPressed (pressed);
158 renewSurface();
159 }
160
161 //------------------------------------------------------------------------------
lock()162 void cPushButton::lock()
163 {
164 isLocked = true;
165 renewSurface();
166 }
167
168 //------------------------------------------------------------------------------
unlock()169 void cPushButton::unlock()
170 {
171 isLocked = false;
172 renewSurface();
173 }
174
175 //------------------------------------------------------------------------------
renewSurface()176 void cPushButton::renewSurface()
177 {
178 if (buttonType == ePushButtonType::Invisible)
179 {
180 surface = nullptr;
181 return;
182 }
183
184 cPosition size;
185 SDL_Rect src;
186 switch (buttonType)
187 {
188 default:
189 case ePushButtonType::StandardBig:
190 src.x = 0;
191 src.y = (isPressed || isLocked) ? 29 : 0;
192 size = cPosition (200, 29);
193 break;
194 case ePushButtonType::StandardSmall:
195 src.x = 0;
196 src.y = (isPressed || isLocked) ? 87 : 58;
197 size = cPosition (150, 29);
198 break;
199 case ePushButtonType::Huge:
200 src.x = (isPressed || isLocked) ? 109 : 0;
201 src.y = 116;
202 size = cPosition (109, 40);
203 break;
204 case ePushButtonType::ArrowUpBig:
205 src.x = (isPressed || isLocked) ? 125 : 97;
206 src.y = 157;
207 size = cPosition (28, 29);
208 break;
209 case ePushButtonType::ArrowDownBig:
210 src.x = (isPressed || isLocked) ? 181 : 153;
211 src.y = 157;
212 size = cPosition (28, 29);
213 break;
214 case ePushButtonType::ArrowLeftBig:
215 src.x = (isPressed || isLocked) ? 293 : 265;
216 src.y = 157;
217 size = cPosition (28, 29);
218 break;
219 case ePushButtonType::ArrowRightBig:
220 src.x = (isPressed || isLocked) ? 237 : 209;
221 src.y = 157;
222 size = cPosition (28, 29);
223 break;
224 case ePushButtonType::ArrowUpSmall:
225 size = cPosition (18, 17);
226 src.x = (isPressed || isLocked) ? 151 + size.x() : 151;
227 src.y = 59;
228 break;
229 case ePushButtonType::ArrowDownSmall:
230 size = cPosition (18, 17);
231 src.x = (isPressed || isLocked) ? 187 + size.x() : 187;
232 src.y = 59;
233 break;
234 case ePushButtonType::ArrowLeftSmall:
235 size = cPosition (18, 17);
236 src.x = (isPressed || isLocked) ? 151 + size.x() : 151;
237 src.y = 76;
238 break;
239 case ePushButtonType::ArrowRightSmall:
240 size = cPosition (18, 17);
241 src.x = (isPressed || isLocked) ? 187 + size.x() : 187;
242 src.y = 76;
243 break;
244 case ePushButtonType::ArrowUpBar:
245 size = cPosition (17, 17);
246 src.x = (isPressed || isLocked) ? 201 + size.x() : 201;
247 src.y = 1;
248 break;
249 case ePushButtonType::ArrowDownBar:
250 size = cPosition (17, 17);
251 src.x = (isPressed || isLocked) ? 201 + size.x() : 201;
252 src.y = 18;
253 break;
254 case ePushButtonType::Angular:
255 size = cPosition (78, 23);
256 src.x = (isPressed || isLocked) ? size.x() : 0;
257 src.y = 196;
258 break;
259 case ePushButtonType::HudHelp:
260 src.x = (isPressed || isLocked) ? 366 : 268;
261 src.y = (isPressed || isLocked) ? 0 : 151;
262 size = cPosition (26, 24);
263 break;
264 case ePushButtonType::HudCenter:
265 src.x = (isPressed || isLocked) ? 0 : 139;
266 src.y = (isPressed || isLocked) ? 21 : 149;
267 size = cPosition (21, 22);
268 break;
269 case ePushButtonType::HudReport:
270 src.x = (isPressed || isLocked) ? 210 : 245;
271 src.y = (isPressed || isLocked) ? 21 : 130;
272 size = cPosition (49, 20);
273 break;
274 case ePushButtonType::HudChat:
275 src.x = (isPressed || isLocked) ? 160 : 196;
276 src.y = (isPressed || isLocked) ? 21 : 129;
277 size = cPosition (49, 20);
278 break;
279 case ePushButtonType::HudNext:
280 src.x = (isPressed || isLocked) ? 288 : 158;
281 src.y = (isPressed || isLocked) ? 0 : 172;
282 size = cPosition (39, 23);
283 break;
284 case ePushButtonType::HudPrev:
285 src.x = (isPressed || isLocked) ? 327 : 198;
286 src.y = (isPressed || isLocked) ? 0 : 172;
287 size = cPosition (38, 23);
288 break;
289 case ePushButtonType::HudDone:
290 src.x = (isPressed || isLocked) ? 262 : 132;
291 src.y = (isPressed || isLocked) ? 0 : 172;
292 size = cPosition (26, 24);
293 break;
294 case ePushButtonType::HudEnd:
295 src.x = (isPressed || isLocked) ? 22 : 0;
296 src.y = (isPressed || isLocked) ? 21 : 151;
297 size = cPosition (70, 17);
298 break;
299 case ePushButtonType::HudPreferences:
300 src.x = (isPressed || isLocked) ? 195 : 0;
301 src.y = (isPressed || isLocked) ? 0 : 169;
302 size = cPosition (67, 20);
303 break;
304 case ePushButtonType::HudFiles:
305 src.x = (isPressed || isLocked) ? 93 : 71;
306 src.y = (isPressed || isLocked) ? 21 : 151;
307 size = cPosition (67, 20);
308 break;
309 case ePushButtonType::HudPlay:
310 src.x = (isPressed || isLocked) ? 157 : 0;
311 src.y = (isPressed || isLocked) ? 0 : 132;
312 size = cPosition (19, 18);
313 break;
314 case ePushButtonType::HudStop:
315 src.x = (isPressed || isLocked) ? 176 : 19;
316 src.y = (isPressed || isLocked) ? 0 : 132;
317 size = cPosition (19, 19);
318 break;
319 case ePushButtonType::UnitContextMenu:
320 src.x = 0;
321 src.y = (isPressed || isLocked) ? 21 : 0;
322 size = cPosition (42, 21);
323 break;
324 case ePushButtonType::Destroy:
325 src.x = (isPressed || isLocked) ? 6 : 15;
326 src.y = (isPressed || isLocked) ? 269 : 13;
327 size = cPosition (59, 56);
328 break;
329 case ePushButtonType::ArrowUpSmallModern:
330 src.x = 224;
331 src.y = (isPressed || isLocked) ? 75 : 83;
332 size = cPosition (16, 8);
333 break;
334 case ePushButtonType::ArrowDownSmallModern:
335 src.x = 224;
336 src.y = (isPressed || isLocked) ? 59 : 67;
337 size = cPosition (16, 8);
338 break;
339 case ePushButtonType::ArrowLeftSmallModern:
340 src.x = (isPressed || isLocked) ? 272 : 264;
341 src.y = 59;
342 size = cPosition (8, 16);
343 break;
344 case ePushButtonType::ArrowRightSmallModern:
345 src.x = (isPressed || isLocked) ? 256 : 248;
346 src.y = 59;
347 size = cPosition (8, 16);
348 break;
349 }
350 resize (size);
351
352 src.w = size.x();
353 src.h = size.y();
354
355 surface = AutoSurface (SDL_CreateRGBSurface (0, src.w, src.h, Video.getColDepth(), 0, 0, 0, 0));
356 SDL_SetColorKey (surface.get(), SDL_TRUE, 0xFF00FF);
357 SDL_FillRect (surface.get(), nullptr, 0xFF00FF);
358
359 SDL_Surface* srcSurface = nullptr;
360
361 if (buttonType >= ePushButtonType::HudHelp && buttonType <= ePushButtonType::HudStop) srcSurface = GraphicsData.gfx_hud_stuff.get();
362 else if (buttonType == ePushButtonType::UnitContextMenu) srcSurface = GraphicsData.gfx_context_menu.get();
363 else if (buttonType == ePushButtonType::Destroy) srcSurface = (isPressed || isLocked) ? GraphicsData.gfx_hud_stuff.get() : GraphicsData.gfx_destruction.get();
364 else srcSurface = GraphicsData.gfx_menu_stuff.get();
365
366 assert (srcSurface != nullptr);
367
368 SDL_BlitSurface (srcSurface, &src, surface.get(), nullptr);
369
370 text = font->shortenStringToSize (text, size.x() - getBordersSize(), fontType);
371 }
372
373 //------------------------------------------------------------------------------
getTextYOffset() const374 int cPushButton::getTextYOffset() const
375 {
376 switch (buttonType)
377 {
378 default:
379 case ePushButtonType::StandardBig:
380 case ePushButtonType::StandardSmall:
381 return 7;
382 case ePushButtonType::Huge:
383 return 11;
384 case ePushButtonType::ArrowUpBig:
385 case ePushButtonType::ArrowDownBig:
386 case ePushButtonType::ArrowLeftBig:
387 case ePushButtonType::ArrowRightBig:
388 case ePushButtonType::ArrowUpSmall:
389 case ePushButtonType::ArrowDownSmall:
390 case ePushButtonType::ArrowLeftSmall:
391 case ePushButtonType::ArrowRightSmall:
392 case ePushButtonType::ArrowUpBar:
393 case ePushButtonType::ArrowDownBar:
394 return -1;
395 case ePushButtonType::Angular:
396 if (isPressed || isLocked) return 5;
397 else return 4;
398 case ePushButtonType::HudNext:
399 case ePushButtonType::HudPrev:
400 case ePushButtonType::HudDone:
401 return 9;
402 case ePushButtonType::HudEnd:
403 if (isPressed || isLocked) return 3;
404 else return 2;
405 case ePushButtonType::HudReport:
406 case ePushButtonType::HudChat:
407 case ePushButtonType::HudPreferences:
408 case ePushButtonType::HudFiles:
409 return 6;
410 case ePushButtonType::UnitContextMenu:
411 return 7;
412 }
413 }
414
415 //------------------------------------------------------------------------------
getBordersSize() const416 int cPushButton::getBordersSize() const
417 {
418 switch (buttonType)
419 {
420 case ePushButtonType::UnitContextMenu:
421 case ePushButtonType::HudDone:
422 return 0;
423 default:
424 return 12;
425 }
426 }
427