1 /***********************************************************************
2 Freeciv - Copyright (C) 2006 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 /* SDL2 */
19 #ifdef SDL2_PLAIN_INCLUDE
20 #include <SDL.h>
21 #else /* SDL2_PLAIN_INCLUDE */
22 #include <SDL2/SDL.h>
23 #endif /* SDL2_PLAIN_INCLUDE */
24
25 /* utility */
26 #include "log.h"
27
28 /* gui-sdl2 */
29 #include "colors.h"
30 #include "graphics.h"
31 #include "gui_tilespec.h"
32 #include "themespec.h"
33
34 #include "widget.h"
35 #include "widget_p.h"
36
37 static int (*baseclass_redraw)(struct widget *pwidget);
38
39 /**************************************************************************
40 Create Icon Button image with text and Icon then blit to Dest(ination)
41 on position pIButton->size.x , pIButton->size.y.
42 WARNING: pDest must exist.
43
44 Text with attributes is taken from pIButton->string_utf8 parameter.
45
46 Graphic for button is taken from pIButton->theme surface
47 and blit to new created image.
48
49 Graphic for Icon is taken from pIButton->theme2 surface and blit to new
50 created image.
51
52 function return (-1) if there are no Icon nor Text.
53 Else return 0.
54 **************************************************************************/
redraw_ibutton(struct widget * pIButton)55 static int redraw_ibutton(struct widget *pIButton)
56 {
57 SDL_Rect dest = { 0, 0, 0, 0 };
58 utf8_str TMPString;
59 SDL_Surface *pButton = NULL, *pText = NULL, *pIcon = pIButton->theme2;
60 Uint16 Ix, Iy, x;
61 Uint16 y = 0; /* FIXME: possibly uninitialized */
62 int ret;
63
64 ret = (*baseclass_redraw)(pIButton);
65 if (ret != 0) {
66 return ret;
67 }
68
69 if (pIButton->string_utf8 != NULL) {
70 /* make copy of string_utf8 */
71 TMPString = *pIButton->string_utf8;
72
73 if (get_wstate(pIButton) == FC_WS_NORMAL) {
74 TMPString.fgcol = *get_theme_color(COLOR_THEME_WIDGET_NORMAL_TEXT);
75 } else if (get_wstate(pIButton) == FC_WS_SELECTED) {
76 TMPString.fgcol = *get_theme_color(COLOR_THEME_WIDGET_SELECTED_TEXT);
77 TMPString.style |= TTF_STYLE_BOLD;
78 } else if (get_wstate(pIButton) == FC_WS_PRESSED) {
79 TMPString.fgcol = *get_theme_color(COLOR_THEME_WIDGET_PRESSED_TEXT);
80 } else if (get_wstate(pIButton) == FC_WS_DISABLED) {
81 TMPString.fgcol = *get_theme_color(COLOR_THEME_WIDGET_DISABLED_TEXT);
82 }
83
84 pText = create_text_surf_from_utf8(&TMPString);
85 }
86
87 if (!pText && !pIcon) {
88 return -1;
89 }
90
91 /* create Button graphic */
92 pButton = create_bcgnd_surf(pIButton->theme, get_wstate(pIButton),
93 pIButton->size.w, pIButton->size.h);
94
95 clear_surface(pIButton->dst->surface, &pIButton->size);
96 alphablit(pButton, NULL, pIButton->dst->surface, &pIButton->size, 255);
97 FREESURFACE(pButton);
98
99 if (pIcon) { /* Icon */
100 if (pText) {
101 if (get_wflags(pIButton) & WF_ICON_CENTER_RIGHT) {
102 Ix = pIButton->size.w - pIcon->w - 5;
103 } else {
104 if (get_wflags(pIButton) & WF_ICON_CENTER) {
105 Ix = (pIButton->size.w - pIcon->w) / 2;
106 } else {
107 Ix = 5;
108 }
109 }
110
111 if (get_wflags(pIButton) & WF_ICON_ABOVE_TEXT) {
112 Iy = 3;
113 y = 3 + pIcon->h + 3 + (pIButton->size.h -
114 (pIcon->h + 6) - pText->h) / 2;
115 } else {
116 if (get_wflags(pIButton) & WF_ICON_UNDER_TEXT) {
117 y = 3 + (pIButton->size.h - (pIcon->h + 3) - pText->h) / 2;
118 Iy = y + pText->h + 3;
119 } else { /* center */
120 Iy = (pIButton->size.h - pIcon->h) / 2;
121 y = (pIButton->size.h - pText->h) / 2;
122 }
123 }
124 } else { /* no text */
125 Iy = (pIButton->size.h - pIcon->h) / 2;
126 Ix = (pIButton->size.w - pIcon->w) / 2;
127 }
128
129 if (get_wstate(pIButton) == FC_WS_PRESSED) {
130 Ix += 1;
131 Iy += 1;
132 }
133
134 dest.x = pIButton->size.x + Ix;
135 dest.y = pIButton->size.y + Iy;
136
137 ret = alphablit(pIcon, NULL, pIButton->dst->surface, &dest, 255);
138 if (ret) {
139 FREESURFACE(pText);
140 return ret - 10;
141 }
142 }
143
144 if (pText) {
145 if (pIcon) {
146 if (!(get_wflags(pIButton) & WF_ICON_ABOVE_TEXT)
147 && !(get_wflags(pIButton) & WF_ICON_UNDER_TEXT)) {
148 if (get_wflags(pIButton) & WF_ICON_CENTER_RIGHT) {
149 if (pIButton->string_utf8->style & SF_CENTER) {
150 x = (pIButton->size.w - (pIcon->w + 5) - pText->w) / 2;
151 } else {
152 if (pIButton->string_utf8->style & SF_CENTER_RIGHT) {
153 x = pIButton->size.w - (pIcon->w + 7) - pText->w;
154 } else {
155 x = 5;
156 }
157 }
158 /* end WF_ICON_CENTER_RIGHT */
159 } else {
160 if (get_wflags(pIButton) & WF_ICON_CENTER) {
161 /* text is blit on icon */
162 goto Alone;
163 /* end WF_ICON_CENTER */
164 } else { /* icon center left - default */
165 if (pIButton->string_utf8->style & SF_CENTER) {
166 x = 5 + pIcon->w + ((pIButton->size.w -
167 (pIcon->w + 5) - pText->w) / 2);
168 } else {
169 if (pIButton->string_utf8->style & SF_CENTER_RIGHT) {
170 x = pIButton->size.w - pText->w - 5;
171 } else { /* text center left */
172 x = 5 + pIcon->w + 3;
173 }
174 }
175 } /* end icon center left - default */
176 }
177 /* 888888888888888888 */
178 } else {
179 goto Alone;
180 }
181 } else {
182 /* !pIcon */
183 y = (pIButton->size.h - pText->h) / 2;
184 Alone:
185 if (pIButton->string_utf8->style & SF_CENTER) {
186 x = (pIButton->size.w - pText->w) / 2;
187 } else {
188 if (pIButton->string_utf8->style & SF_CENTER_RIGHT) {
189 x = pIButton->size.w - pText->w - 5;
190 } else {
191 x = 5;
192 }
193 }
194 }
195
196 if (get_wstate(pIButton) == FC_WS_PRESSED) {
197 x += 1;
198 } else {
199 y -= 1;
200 }
201
202 dest.x = pIButton->size.x + x;
203 dest.y = pIButton->size.y + y;
204
205 ret = alphablit(pText, NULL, pIButton->dst->surface, &dest, 255);
206 }
207
208 FREESURFACE(pText);
209
210 return 0;
211 }
212
213 /**************************************************************************
214 Create Icon Button image with text and Icon then blit to Dest(ination)
215 on position pTIButton->size.x, pTIButton->size.y. WARNING: pDest must
216 exist.
217
218 Text with attributes is taken from pTIButton->string_utf8 parameter.
219
220 Graphic for button is taken from pTIButton->theme surface
221 and blit to new created image.
222
223 Graphic for Icon Theme is taken from pTIButton->theme2 surface
224 and blit to new created image.
225
226 function return (-1) if there are no Icon and Text. Else return 0.
227 **************************************************************************/
redraw_tibutton(struct widget * pTIButton)228 static int redraw_tibutton(struct widget *pTIButton)
229 {
230 int iRet = 0;
231 SDL_Surface *pIcon;
232 SDL_Surface *pCopy_Of_Icon_Theme;
233
234 iRet = (*baseclass_redraw)(pTIButton);
235 if (iRet != 0) {
236 return iRet;
237 }
238
239 pIcon = create_icon_from_theme(pTIButton->theme2, get_wstate(pTIButton));
240 pCopy_Of_Icon_Theme = pTIButton->theme2;
241
242 pTIButton->theme2 = pIcon;
243
244 iRet = redraw_ibutton(pTIButton);
245
246 FREESURFACE(pTIButton->theme2);
247 pTIButton->theme2 = pCopy_Of_Icon_Theme;
248
249 return iRet;
250 }
251
252 /**************************************************************************
253 Create ( malloc ) Icon (theme)Button Widget structure.
254
255 Icon graphic is taken from 'pIcon' surface (don't change with button
256 changes ); Button Theme graphic is taken from current_theme->Button surface;
257 Text is taken from 'pstr'.
258
259 This function determinate future size of Button ( width, height ) and
260 save this in: pWidget->size rectangle ( SDL_Rect )
261
262 function return pointer to allocated Button Widget.
263 **************************************************************************/
create_icon_button(SDL_Surface * pIcon,struct gui_layer * pDest,utf8_str * pstr,Uint32 flags)264 struct widget *create_icon_button(SDL_Surface *pIcon, struct gui_layer *pDest,
265 utf8_str *pstr, Uint32 flags)
266 {
267 SDL_Rect buf = {0, 0, 0, 0};
268 int w = 0, h = 0;
269 struct widget *pButton;
270
271 if (!pIcon && !pstr) {
272 return NULL;
273 }
274
275 pButton = widget_new();
276
277 pButton->theme = current_theme->Button;
278 pButton->theme2 = pIcon;
279 pButton->string_utf8 = pstr;
280 set_wflag(pButton, (WF_FREE_STRING | flags));
281 set_wstate(pButton, FC_WS_DISABLED);
282 set_wtype(pButton, WT_I_BUTTON);
283 pButton->mod = KMOD_NONE;
284 pButton->dst = pDest;
285
286 baseclass_redraw = pButton->redraw;
287 pButton->redraw = redraw_ibutton;
288
289 if (pstr) {
290 pButton->string_utf8->style |= SF_CENTER;
291 /* if BOLD == true then longest wight */
292 if (!(pstr->style & TTF_STYLE_BOLD)) {
293 pstr->style |= TTF_STYLE_BOLD;
294 utf8_str_size(pstr, &buf);
295 pstr->style &= ~TTF_STYLE_BOLD;
296 } else {
297 utf8_str_size(pstr, &buf);
298 }
299
300 w = MAX(w, buf.w);
301 h = MAX(h, buf.h);
302 }
303
304 if (pIcon) {
305 if (pstr) {
306 if ((flags & WF_ICON_UNDER_TEXT) || (flags & WF_ICON_ABOVE_TEXT)) {
307 w = MAX(w, pIcon->w + adj_size(2));
308 h = MAX(h, buf.h + pIcon->h + adj_size(4));
309 } else {
310 w = MAX(w, buf.w + pIcon->w + adj_size(20));
311 h = MAX(h, pIcon->h + adj_size(2));
312 }
313 } else {
314 w = MAX(w, pIcon->w + adj_size(2));
315 h = MAX(h, pIcon->h + adj_size(2));
316 }
317 } else {
318 w += adj_size(10);
319 h += adj_size(2);
320 }
321
322 correct_size_bcgnd_surf(current_theme->Button, &w, &h);
323
324 pButton->size.w = w;
325 pButton->size.h = h;
326
327 return pButton;
328 }
329
330 /**************************************************************************
331 Create ( malloc ) Theme Icon (theme)Button Widget structure.
332
333 Icon Theme graphic is taken from 'pIcon_theme' surface ( change with
334 button changes ); Button Theme graphic is taken from current_theme->Button
335 surface; Text is taken from 'pstr'.
336
337 This function determinate future size of Button ( width, height ) and
338 save this in: pWidget->size rectangle ( SDL_Rect )
339
340 function return pointer to allocated Button Widget.
341 **************************************************************************/
create_themeicon_button(SDL_Surface * pIcon_theme,struct gui_layer * pDest,utf8_str * pstr,Uint32 flags)342 struct widget *create_themeicon_button(SDL_Surface *pIcon_theme,
343 struct gui_layer *pDest,
344 utf8_str *pstr,
345 Uint32 flags)
346 {
347 /* extract a single icon */
348 SDL_Surface *pIcon = create_icon_from_theme(pIcon_theme, 1);
349 struct widget *pButton = create_icon_button(pIcon, pDest, pstr, flags);
350
351 FREESURFACE(pButton->theme2);
352 pButton->theme2 = pIcon_theme;
353 set_wtype(pButton, WT_TI_BUTTON);
354
355 pButton->redraw = redraw_tibutton;
356
357 return pButton;
358 }
359
360 /**************************************************************************
361 Create Button image with text and Icon. Then blit to Main.screen on
362 position start_x, start_y.
363
364 Text with atributes is taken from pButton->string_utf8 parameter.
365
366 Graphic for button is taken from pButton->theme surface and blit to new
367 created image.
368
369 Graphic for Icon theme is taken from pButton->theme2 surface and blit to
370 new created image.
371
372 function return (-1) if there are no Icon and Text.
373 Else return 0.
374 **************************************************************************/
draw_tibutton(struct widget * pButton,Sint16 start_x,Sint16 start_y)375 int draw_tibutton(struct widget *pButton, Sint16 start_x, Sint16 start_y)
376 {
377 pButton->size.x = start_x;
378 pButton->size.y = start_y;
379
380 return redraw_tibutton(pButton);
381 }
382
383 /**************************************************************************
384 Create Button image with text and Icon.
385 Then blit to Main.screen on position start_x, start_y.
386
387 Text with atributes is taken from pButton->string_utf8 parameter.
388
389 Graphic for button is taken from pButton->theme surface
390 and blit to new created image.
391
392 Graphic for Icon is taken from pButton->theme2 surface
393 and blit to new created image.
394
395 function return (-1) if there are no Icon and Text.
396 Else return 0.
397 **************************************************************************/
draw_ibutton(struct widget * pButton,Sint16 start_x,Sint16 start_y)398 int draw_ibutton(struct widget *pButton, Sint16 start_x, Sint16 start_y)
399 {
400 pButton->size.x = start_x;
401 pButton->size.y = start_y;
402
403 return redraw_ibutton(pButton);
404 }
405