When mixer is not available, recommend SDL2_mixer instead of SDL1.2 mixer
[freeciv.git] / client / gui-sdl / widget_label.c
blob61c0b2a5f3ebf33aef5b4f8370a1e91dab8e1e56
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* SDL */
19 #include <SDL/SDL.h>
21 /* utility */
22 #include "log.h"
23 #include "mem.h"
25 /* client/gui-sdl */
26 #include "colors.h"
27 #include "graphics.h"
28 #include "themespec.h"
30 #include "widget.h"
31 #include "widget_p.h"
33 static int (*baseclass_redraw)(struct widget *pwidget);
35 /**************************************************************************
36 ...
37 **************************************************************************/
38 static inline int redraw_themelabel2(struct widget *pLabel)
41 SDL_Rect src = {0,0, pLabel->size.w, pLabel->size.h};
42 SDL_Rect dst = {pLabel->size.x, pLabel->size.y, 0, 0};
43 /*
44 if (!pLabel) {
45 return -3;
48 if(get_wstate(pLabel) == FC_WS_SELLECTED) {
49 src.y = pLabel->size.h;
52 return alphablit(pLabel->theme, &src, pLabel->dst->surface, &dst);
55 /**************************************************************************
56 ...
57 **************************************************************************/
58 static int redraw_label(struct widget *pLabel)
60 int ret;
61 SDL_Rect area = pLabel->size;
62 SDL_Color bar_color = *get_theme_color(COLOR_THEME_LABEL_BAR);
63 SDL_Color backup_color = {0, 0, 0, 0};
65 ret = (*baseclass_redraw)(pLabel);
66 if (ret != 0) {
67 return ret;
70 if(get_wtype(pLabel) == WT_T2_LABEL) {
71 return redraw_themelabel2(pLabel);
74 /* redraw sellect bar */
75 if (get_wstate(pLabel) == FC_WS_SELLECTED) {
76 if(get_wflags(pLabel) & WF_SELLECT_WITHOUT_BAR) {
77 if (pLabel->string16) {
78 backup_color = pLabel->string16->fgcol;
79 pLabel->string16->fgcol = bar_color;
80 if(pLabel->string16->style & TTF_STYLE_BOLD) {
81 pLabel->string16->style |= TTF_STYLE_UNDERLINE;
82 } else {
83 pLabel->string16->style |= TTF_STYLE_BOLD;
86 } else {
87 SDL_FillRectAlpha(pLabel->dst->surface, &area, &bar_color);
91 /* redraw icon label */
92 ret = redraw_iconlabel(pLabel);
94 if ((get_wstate(pLabel) == FC_WS_SELLECTED) && (pLabel->string16)) {
95 if(get_wflags(pLabel) & WF_SELLECT_WITHOUT_BAR) {
96 if (pLabel->string16->style & TTF_STYLE_UNDERLINE) {
97 pLabel->string16->style &= ~TTF_STYLE_UNDERLINE;
98 } else {
99 pLabel->string16->style &= ~TTF_STYLE_BOLD;
101 pLabel->string16->fgcol = backup_color;
102 } else {
103 if(pLabel->string16->render == 3) {
104 pLabel->string16->bgcol = backup_color;
109 return ret;
112 /**************************************************************************
114 **************************************************************************/
115 void remake_label_size(struct widget *pLabel)
117 SDL_Surface *pIcon = pLabel->theme;
118 SDL_String16 *pText = pLabel->string16;
119 Uint32 flags = get_wflags(pLabel);
120 SDL_Rect buf = { 0, 0, 0, 0 };
121 Uint16 w = 0, h = 0, space;
123 if (flags & WF_DRAW_TEXT_LABEL_WITH_SPACE) {
124 space = adj_size(10);
125 } else {
126 space = 0;
129 if (pText) {
130 bool without_box = ((get_wflags(pLabel) & WF_SELLECT_WITHOUT_BAR) == WF_SELLECT_WITHOUT_BAR);
131 bool bold = TRUE;
133 if (without_box)
135 bold = ((pText->style & TTF_STYLE_BOLD) == TTF_STYLE_BOLD);
136 pText->style |= TTF_STYLE_BOLD;
139 buf = str16size(pText);
141 if (without_box && !bold)
143 pText->style &= ~TTF_STYLE_BOLD;
146 w = MAX(w, buf.w + space);
147 h = MAX(h, buf.h);
150 if (pIcon) {
151 if (pText) {
152 if ((flags & WF_ICON_UNDER_TEXT) || (flags & WF_ICON_ABOVE_TEXT)) {
153 w = MAX(w, pIcon->w + space);
154 h = MAX(h, buf.h + pIcon->h + adj_size(3));
155 } else {
156 if (flags & WF_ICON_CENTER) {
157 w = MAX(w, pIcon->w + space);
158 h = MAX(h, pIcon->h);
159 } else {
160 w = MAX(w, buf.w + pIcon->w + adj_size(5) + space);
161 h = MAX(h, pIcon->h);
164 } /* pText */
165 else {
166 w = MAX(w, pIcon->w + space);
167 h = MAX(h, pIcon->h);
171 /* pIcon */
172 pLabel->size.w = w;
173 pLabel->size.h = h;
176 /**************************************************************************
177 ThemeLabel is String16 with Background ( pIcon ).
178 **************************************************************************/
179 struct widget * create_themelabel(SDL_Surface *pIcon, struct gui_layer *pDest,
180 SDL_String16 *pText, Uint16 w, Uint16 h, Uint32 flags)
182 struct widget *pLabel = NULL;
184 if (!pIcon && !pText) {
185 return NULL;
188 pLabel = widget_new();
189 pLabel->theme = pIcon;
190 pLabel->string16 = pText;
191 set_wflag(pLabel,
192 (WF_ICON_CENTER | WF_FREE_STRING | WF_FREE_GFX |
193 WF_RESTORE_BACKGROUND | flags));
194 set_wstate(pLabel, FC_WS_DISABLED);
195 set_wtype(pLabel, WT_T_LABEL);
196 pLabel->mod = KMOD_NONE;
197 pLabel->dst = pDest;
199 baseclass_redraw = pLabel->redraw;
200 pLabel->redraw = redraw_label;
202 remake_label_size(pLabel);
204 pLabel->size.w = MAX(pLabel->size.w, w);
205 pLabel->size.h = MAX(pLabel->size.h, h);
207 return pLabel;
210 /**************************************************************************
211 this Label is String16 with Icon.
212 **************************************************************************/
213 struct widget * create_iconlabel(SDL_Surface *pIcon, struct gui_layer *pDest,
214 SDL_String16 *pText, Uint32 flags)
216 struct widget *pILabel = NULL;
218 pILabel = widget_new();
220 pILabel->theme = pIcon;
221 pILabel->string16 = pText;
222 set_wflag(pILabel, WF_FREE_STRING | WF_FREE_GFX | flags);
223 set_wstate(pILabel, FC_WS_DISABLED);
224 set_wtype(pILabel, WT_I_LABEL);
225 pILabel->mod = KMOD_NONE;
226 pILabel->dst = pDest;
228 baseclass_redraw = pILabel->redraw;
229 pILabel->redraw = redraw_label;
231 remake_label_size(pILabel);
233 return pILabel;
236 /**************************************************************************
237 ThemeLabel is String16 with Background ( pIcon ).
238 **************************************************************************/
239 struct widget * create_themelabel2(SDL_Surface *pIcon, struct gui_layer *pDest,
240 SDL_String16 *pText, Uint16 w, Uint16 h, Uint32 flags)
242 struct widget *pLabel = NULL;
243 SDL_Surface *pBuf = NULL, *pTheme = NULL;
244 SDL_Rect area;
245 SDL_Color store = {0, 0, 0, 0};
246 SDL_Color bg_color = *get_theme_color(COLOR_THEME_THEMELABEL2_BG);
247 Uint32 colorkey;
249 if (!pIcon && !pText) {
250 return NULL;
253 pLabel = widget_new();
254 pLabel->theme = pIcon;
255 pLabel->string16 = pText;
256 set_wflag(pLabel, (WF_FREE_THEME | WF_FREE_STRING | WF_FREE_GFX | flags));
257 set_wstate(pLabel, FC_WS_DISABLED);
258 set_wtype(pLabel, WT_T2_LABEL);
259 pLabel->mod = KMOD_NONE;
260 baseclass_redraw = pLabel->redraw;
261 pLabel->redraw = redraw_label;
263 remake_label_size(pLabel);
265 pLabel->size.w = MAX(pLabel->size.w, w);
266 pLabel->size.h = MAX(pLabel->size.h, h);
268 pBuf = create_surf_alpha(pLabel->size.w, pLabel->size.h * 2, SDL_SWSURFACE);
270 if(flags & WF_RESTORE_BACKGROUND) {
271 pTheme = SDL_DisplayFormatAlpha(pBuf);
272 FREESURFACE(pBuf);
273 } else {
274 pTheme = pBuf;
277 colorkey = SDL_MapRGBA(pTheme->format, pText->bgcol.r,
278 pText->bgcol.g, pText->bgcol.b, pText->bgcol.unused);
279 SDL_FillRect(pTheme, NULL, colorkey);
281 pLabel->size.x = 0;
282 pLabel->size.y = 0;
283 area = pLabel->size;
284 pLabel->dst = gui_layer_new(0, 0, pTheme);
286 /* normal */
287 redraw_iconlabel(pLabel);
289 /* sellected */
290 area.x = 0;
291 area.y = pLabel->size.h;
293 if(flags & WF_RESTORE_BACKGROUND) {
294 SDL_FillRect(pTheme, &area, map_rgba(pTheme->format, bg_color));
295 store = pText->bgcol;
296 SDL_GetRGBA(getpixel(pTheme, area.x , area.y), pTheme->format,
297 &pText->bgcol.r, &pText->bgcol.g,
298 &pText->bgcol.b, &pText->bgcol.unused);
299 } else {
300 SDL_FillRectAlpha(pTheme, &area, &bg_color);
303 pLabel->size.y = pLabel->size.h;
304 redraw_iconlabel(pLabel);
306 if(flags & WF_RESTORE_BACKGROUND) {
307 pText->bgcol = store;
310 pLabel->size.x = 0;
311 pLabel->size.y = 0;
312 if(flags & WF_FREE_THEME) {
313 FREESURFACE(pLabel->theme);
315 pLabel->theme = pTheme;
316 FC_FREE(pLabel->dst);
317 pLabel->dst = pDest;
318 return pLabel;
321 struct widget * convert_iconlabel_to_themeiconlabel2(struct widget *pIconLabel)
323 SDL_Rect start, area;
324 SDL_Color store = {0, 0, 0, 0};
325 SDL_Color bg_color = *get_theme_color(COLOR_THEME_THEMELABEL2_BG);
326 Uint32 colorkey, flags = get_wflags(pIconLabel);
327 SDL_Surface *pDest, *pTheme, *pBuf = create_surf_alpha(pIconLabel->size.w,
328 pIconLabel->size.h * 2, SDL_SWSURFACE);
330 if(flags & WF_RESTORE_BACKGROUND) {
331 pTheme = SDL_DisplayFormatAlpha(pBuf);
332 FREESURFACE(pBuf);
333 } else {
334 pTheme = pBuf;
337 colorkey = SDL_MapRGBA(pTheme->format, pIconLabel->string16->bgcol.r,
338 pIconLabel->string16->bgcol.g,
339 pIconLabel->string16->bgcol.b,
340 pIconLabel->string16->bgcol.unused);
341 SDL_FillRect(pTheme, NULL, colorkey);
343 start = pIconLabel->size;
344 pIconLabel->size.x = 0;
345 pIconLabel->size.y = 0;
346 area = start;
347 pDest = pIconLabel->dst->surface;
348 pIconLabel->dst->surface = pTheme;
350 /* normal */
351 redraw_iconlabel(pIconLabel);
353 /* sellected */
354 area.x = 0;
355 area.y = pIconLabel->size.h;
357 if(flags & WF_RESTORE_BACKGROUND) {
358 SDL_FillRect(pTheme, &area, map_rgba(pTheme->format, bg_color));
359 store = pIconLabel->string16->bgcol;
360 SDL_GetRGBA(getpixel(pTheme, area.x , area.y), pTheme->format,
361 &pIconLabel->string16->bgcol.r, &pIconLabel->string16->bgcol.g,
362 &pIconLabel->string16->bgcol.b,
363 &pIconLabel->string16->bgcol.unused);
364 } else {
365 SDL_FillRectAlpha(pTheme, &area, &bg_color);
368 pIconLabel->size.y = pIconLabel->size.h;
369 redraw_iconlabel(pIconLabel);
371 if(flags & WF_RESTORE_BACKGROUND) {
372 pIconLabel->string16->bgcol = store;
375 pIconLabel->size = start;
376 if(flags & WF_FREE_THEME) {
377 FREESURFACE(pIconLabel->theme);
379 pIconLabel->theme = pTheme;
380 if(flags & WF_FREE_STRING) {
381 FREESTRING16(pIconLabel->string16);
383 pIconLabel->dst->surface = pDest;
384 set_wtype(pIconLabel, WT_T2_LABEL);
386 pIconLabel->redraw = redraw_label;
388 return pIconLabel;
391 #if 0
392 /**************************************************************************
394 **************************************************************************/
395 static int redraw_themelabel(struct widget *pLabel)
397 int ret;
398 Sint16 x, y;
399 SDL_Surface *pText = NULL;
401 if (!pLabel) {
402 return -3;
405 if ((pText = create_text_surf_from_str16(pLabel->string16)) == NULL) {
406 return (-4);
409 if (pLabel->string16->style & SF_CENTER) {
410 x = (pLabel->size.w - pText->w) / 2;
411 } else {
412 if (pLabel->string16->style & SF_CENTER_RIGHT) {
413 x = pLabel->size.w - pText->w - adj_size(5);
414 } else {
415 x = adj_size(5);
419 y = (pLabel->size.h - pText->h) / 2;
421 /* redraw theme */
422 if (pLabel->theme) {
423 ret = blit_entire_src(pLabel->theme, pLabel->dst->surface, pLabel->size.x, pLabel->size.y);
424 if (ret) {
425 return ret;
429 ret = blit_entire_src(pText, pLabel->dst->surface, pLabel->size.x + x, pLabel->size.y + y);
431 FREESURFACE(pText);
433 return ret;
435 #endif
437 /**************************************************************************
439 **************************************************************************/
440 int redraw_iconlabel(struct widget *pLabel)
442 int space, ret = 0; /* FIXME: possibly uninitialized */
443 Sint16 x, xI, yI;
444 Sint16 y = 0; /* FIXME: possibly uninitialized */
445 SDL_Surface *pText;
446 SDL_Rect dst;
447 Uint32 flags;
449 if (!pLabel) {
450 return -3;
453 SDL_SetClipRect(pLabel->dst->surface, &pLabel->size);
455 flags = get_wflags(pLabel);
457 if (flags & WF_DRAW_TEXT_LABEL_WITH_SPACE) {
458 space = adj_size(5);
459 } else {
460 space = 0;
463 pText = create_text_surf_from_str16(pLabel->string16);
465 if (pLabel->theme) { /* Icon */
466 if (pText) {
467 if (flags & WF_ICON_CENTER_RIGHT) {
468 xI = pLabel->size.w - pLabel->theme->w - space;
469 } else {
470 if (flags & WF_ICON_CENTER) {
471 xI = (pLabel->size.w - pLabel->theme->w) / 2;
472 } else {
473 xI = space;
477 if (flags & WF_ICON_ABOVE_TEXT) {
478 yI = 0;
479 y = pLabel->theme->h + adj_size(3)
480 + (pLabel->size.h - (pLabel->theme->h + adj_size(3)) - pText->h) / 2;
481 } else {
482 if (flags & WF_ICON_UNDER_TEXT) {
483 y = (pLabel->size.h - (pLabel->theme->h + adj_size(3)) - pText->h) / 2;
484 yI = y + pText->h + adj_size(3);
485 } else {
486 yI = (pLabel->size.h - pLabel->theme->h) / 2;
487 y = (pLabel->size.h - pText->h) / 2;
490 } /* pText */
491 else {
492 #if 0
493 yI = (pLabel->size.h - pLabel->theme->h) / 2;
494 xI = (pLabel->size.w - pLabel->theme->w) / 2;
495 #endif
496 yI = 0;
497 xI = space;
500 dst.x = pLabel->size.x + xI;
501 dst.y = pLabel->size.y + yI;
503 ret = alphablit(pLabel->theme, NULL, pLabel->dst->surface, &dst);
505 if (ret) {
506 return ret - 10;
510 if (pText) {
511 if (pLabel->theme) { /* Icon */
512 if (!(flags & WF_ICON_ABOVE_TEXT) && !(flags & WF_ICON_UNDER_TEXT)) {
513 if (flags & WF_ICON_CENTER_RIGHT) {
514 if (pLabel->string16->style & SF_CENTER) {
515 x = (pLabel->size.w - (pLabel->theme->w + 5 + space) -
516 pText->w) / 2;
517 } else {
518 if (pLabel->string16->style & SF_CENTER_RIGHT) {
519 x = pLabel->size.w - (pLabel->theme->w + 5 + space) - pText->w;
520 } else {
521 x = space;
524 } /* WF_ICON_CENTER_RIGHT */
525 else {
526 if (flags & WF_ICON_CENTER) {
527 /* text is blit on icon */
528 goto Alone;
529 } else { /* WF_ICON_CENTER_LEFT */
530 if (pLabel->string16->style & SF_CENTER) {
531 x = space + pLabel->theme->w + adj_size(5) + ((pLabel->size.w -
532 (space +
533 pLabel->theme->w + adj_size(5)) -
534 pText->w) / 2);
535 } else {
536 if (pLabel->string16->style & SF_CENTER_RIGHT) {
537 x = pLabel->size.w - pText->w - space;
538 } else {
539 x = space + pLabel->theme->w + adj_size(5);
542 } /* WF_ICON_CENTER_LEFT */
544 } /* !WF_ICON_ABOVE_TEXT && !WF_ICON_UNDER_TEXT */
545 else {
546 goto Alone;
548 } /* pLabel->theme == Icon */
549 else {
550 y = (pLabel->size.h - pText->h) / 2;
551 Alone:
552 if (pLabel->string16->style & SF_CENTER) {
553 x = (pLabel->size.w - pText->w) / 2;
554 } else {
555 if (pLabel->string16->style & SF_CENTER_RIGHT) {
556 x = pLabel->size.w - pText->w - space;
557 } else {
558 x = space;
563 dst.x = pLabel->size.x + x;
564 dst.y = pLabel->size.y + y;
566 ret = alphablit(pText, NULL, pLabel->dst->surface, &dst);
567 FREESURFACE(pText);
571 SDL_SetClipRect(pLabel->dst->surface, NULL);
572 return ret;
575 /**************************************************************************
577 **************************************************************************/
578 int draw_label(struct widget *pLabel, Sint16 start_x, Sint16 start_y)
580 pLabel->size.x = start_x;
581 pLabel->size.y = start_y;
582 return redraw_label(pLabel);