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)
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 ***********************************************************************/
15 #include <fc_config.h>
19 #ifdef SDL2_PLAIN_INCLUDE
21 #else /* SDL2_PLAIN_INCLUDE */
23 #endif /* SDL2_PLAIN_INCLUDE */
27 #include "string_vector.h"
31 #include "gui_iconv.h"
33 #include "gui_string.h"
34 #include "gui_tilespec.h"
40 struct widget
*begin_widget_list
;
41 struct widget
*end_widget_list
;
44 static int (*baseclass_redraw
) (struct widget
*widget
) = NULL
;
47 /****************************************************************************
48 Redraw the combo box widget.
49 ****************************************************************************/
50 static int combo_redraw(struct widget
*combo
)
52 SDL_Rect dest
= { combo
->size
.x
, combo
->size
.y
, 0, 0 };
53 SDL_Surface
*text
, *surface
;
54 struct combo_menu
*menu
;
57 ret
= baseclass_redraw(combo
);
62 surface
= create_bcgnd_surf(combo
->theme
, get_wstate(combo
),
63 combo
->size
.w
, combo
->size
.h
);
65 if (NULL
== surface
) {
70 alphablit(surface
, NULL
, combo
->dst
->surface
, &dest
, 255);
72 /* Set position and blit text. */
73 text
= create_text_surf_from_utf8(combo
->string_utf8
);
75 dest
.y
+= (surface
->h
- surface
->h
) / 2;
76 /* Blit centred text to botton. */
77 if (combo
->string_utf8
->style
& SF_CENTER
) {
78 dest
.x
+= (surface
->w
- text
->w
) / 2;
80 if (combo
->string_utf8
->style
& SF_CENTER_RIGHT
) {
81 dest
.x
+= surface
->w
- text
->w
- adj_size(5);
83 dest
.x
+= adj_size(5); /* center left */
87 alphablit(text
, NULL
, combo
->dst
->surface
, &dest
, 255);
96 menu
= (struct combo_menu
*) combo
->private_data
.ptr
;
98 ret
= redraw_group(menu
->begin_widget_list
, menu
->end_widget_list
, 0);
104 /****************************************************************************
105 User interacted with the combo menu window.
106 ****************************************************************************/
107 static int combo_menu_callback(struct widget
*window
)
109 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
110 struct combo_menu
*menu
=
111 (struct combo_menu
*)window
->data
.widget
->private_data
.ptr
;
113 move_window_group(menu
->begin_widget_list
, menu
->end_widget_list
);
119 /****************************************************************************
120 User interacted with a single item of the combo menu.
121 ****************************************************************************/
122 static int combo_menu_item_callback(struct widget
*label
)
124 struct widget
*combo
= label
->data
.widget
;
126 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
127 copy_chars_to_utf8_str(combo
->string_utf8
, label
->string_utf8
->text
);
128 widget_redraw(combo
);
129 widget_mark_dirty(combo
);
131 combo_popdown(combo
);
136 /****************************************************************************
137 Popup the combo box widget.
138 ****************************************************************************/
139 void combo_popup(struct widget
*combo
)
141 struct combo_menu
*menu
;
142 struct widget
*window
, *label
= NULL
;
143 int longest
= 0, h
= 0, x
, y
;
145 fc_assert_ret(NULL
!= combo
);
146 fc_assert_ret(WT_COMBO
== get_wtype(combo
));
148 if (NULL
!= combo
->private_data
.ptr
) {
152 if (0 >= strvec_size(combo
->data
.vector
)) {
157 window
= create_window_skeleton(NULL
, NULL
, 0);
158 window
->action
= combo_menu_callback
;
159 window
->data
.widget
= combo
;
160 set_wstate(window
, FC_WS_NORMAL
);
161 add_to_gui_list(ID_COMBO_MENU
, window
);
164 strvec_iterate(combo
->data
.vector
, string
) {
165 label
= create_iconlabel_from_chars(NULL
, window
->dst
, string
,
166 adj_font(10), WF_RESTORE_BACKGROUND
);
167 label
->action
= combo_menu_item_callback
;
168 label
->data
.widget
= combo
;
169 set_wstate(label
, FC_WS_NORMAL
);
170 add_to_gui_list(ID_LABEL
, label
);
172 longest
= MAX(longest
, label
->size
.w
);
173 widget_set_position(label
, adj_size(10), h
);
175 } strvec_iterate_end
;
177 /* Resize and relocate the window. */
178 resize_window(window
, NULL
, NULL
, longest
+ 2 * adj_size(10), h
);
180 x
= combo
->size
.x
+ combo
->dst
->dest_rect
.x
;
181 if (x
+ window
->size
.w
> main_window_width()) {
182 x
= main_window_width() - window
->size
.w
;
188 y
= combo
->size
.y
- h
+ combo
->dst
->dest_rect
.y
;
189 if (y
+ window
->size
.h
> main_window_height()) {
190 y
= main_window_height() - window
->size
.h
;
196 widget_set_position(window
, x
, y
);
199 menu
= fc_malloc(sizeof(*menu
));
200 menu
->begin_widget_list
= label
;
201 menu
->end_widget_list
= window
;
202 combo
->private_data
.ptr
= menu
;
205 redraw_group(menu
->begin_widget_list
, menu
->end_widget_list
, 0);
206 widget_mark_dirty(window
);
210 /****************************************************************************
211 Popdown the combo box widget.
212 ****************************************************************************/
213 void combo_popdown(struct widget
*combo
)
215 struct combo_menu
*menu
;
217 fc_assert_ret(NULL
!= combo
);
218 fc_assert_ret(WT_COMBO
== get_wtype(combo
));
220 menu
= (struct combo_menu
*) combo
->private_data
.ptr
;
225 widget_mark_dirty(menu
->end_widget_list
);
226 popdown_window_group_dialog(menu
->begin_widget_list
,
227 menu
->end_widget_list
);
229 combo
->private_data
.ptr
= NULL
;
233 /****************************************************************************
234 Create a combo box widget.
235 ****************************************************************************/
236 struct widget
*combo_new(SDL_Surface
*background
, struct gui_layer
*dest
,
237 utf8_str
*pstr
, const struct strvec
*vector
,
238 int length
, Uint32 flags
)
240 SDL_Rect buf
= {0, 0, 0, 0};
241 struct widget
*combo
= widget_new();
243 combo
->theme
= current_theme
->Edit
;
244 combo
->theme2
= background
;
245 combo
->string_utf8
= pstr
;
246 set_wflag(combo
, WF_FREE_STRING
| WF_FREE_GFX
| flags
);
247 set_wstate(combo
, FC_WS_DISABLED
);
248 set_wtype(combo
, WT_COMBO
);
249 combo
->mod
= KMOD_NONE
;
251 baseclass_redraw
= combo
->redraw
;
252 combo
->redraw
= combo_redraw
;
253 combo
->destroy
= combo_popdown
;
256 combo
->string_utf8
->style
|= SF_CENTER
;
257 utf8_str_size(pstr
, &buf
);
258 buf
.h
+= adj_size(4);
261 length
= MAX(length
, buf
.w
+ adj_size(10));
262 correct_size_bcgnd_surf(current_theme
->Edit
, &length
, &buf
.h
);
263 combo
->size
.w
= buf
.w
+ adj_size(10);
264 combo
->size
.h
= buf
.h
;
269 combo
->dst
= add_gui_layer(combo
->size
.w
, combo
->size
.h
);
271 combo
->data
.vector
= vector
;
272 combo
->private_data
.ptr
= NULL
;