1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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>
21 #ifdef SDL2_PLAIN_INCLUDE
23 #else /* SDL2_PLAIN_INCLUDE */
25 #endif /* SDL2_PLAIN_INCLUDE */
28 #include "bitvector.h"
34 #include "fc_types.h" /* bv_player */
38 #include "client_main.h"
47 #include "gui_tilespec.h"
54 static struct ADVANCED_DLG
*pGotoDlg
= NULL
;
55 bv_player all_players
;
56 static bool GOTO
= TRUE
;
58 static void update_goto_dialog(void);
60 /**************************************************************************
61 User interacted with goto dialog window.
62 **************************************************************************/
63 static int goto_dialog_window_callback(struct widget
*pWindow
)
65 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
66 move_window_group(pGotoDlg
->pBeginWidgetList
, pWindow
);
72 /**************************************************************************
74 **************************************************************************/
75 static int exit_goto_dialog_callback(struct widget
*pWidget
)
77 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
78 popdown_goto_airlift_dialog();
85 /**************************************************************************
86 Toggle whether player cities are listed as possible destinations.
87 **************************************************************************/
88 static int toggle_goto_nations_cities_dialog_callback(struct widget
*pWidget
)
90 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
91 int plr_id
= player_index(player_by_number(MAX_ID
- pWidget
->ID
));
93 if (BV_ISSET(all_players
, plr_id
)) {
94 BV_CLR(all_players
, plr_id
);
96 BV_SET(all_players
, plr_id
);
104 /**************************************************************************
105 User has selected city for unit to go to.
106 **************************************************************************/
107 static int goto_city_callback(struct widget
*pWidget
)
109 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
110 struct city
*pDestcity
= game_city_by_number(MAX_ID
- pWidget
->ID
);
113 struct unit
*pUnit
= head_of_units_in_focus();
117 send_goto_tile(pUnit
, pDestcity
->tile
);
119 request_unit_airlift(pUnit
, pDestcity
);
124 popdown_goto_airlift_dialog();
131 /**************************************************************************
133 **************************************************************************/
134 static void update_goto_dialog(void)
136 struct widget
*pBuf
= NULL
, *pAdd_Dock
, *pLast
;
137 SDL_Surface
*pLogo
= NULL
;
141 struct player
*owner
= NULL
;
143 if (pGotoDlg
->pEndActiveWidgetList
) {
144 pAdd_Dock
= pGotoDlg
->pEndActiveWidgetList
->next
;
145 pGotoDlg
->pBeginWidgetList
= pAdd_Dock
;
146 del_group(pGotoDlg
->pBeginActiveWidgetList
, pGotoDlg
->pEndActiveWidgetList
);
147 pGotoDlg
->pActiveWidgetList
= NULL
;
149 pAdd_Dock
= pGotoDlg
->pBeginWidgetList
;
154 players_iterate(pPlayer
) {
155 if (!BV_ISSET(all_players
, player_index(pPlayer
))) {
159 city_list_iterate(pPlayer
->cities
, pCity
) {
161 /* FIXME: should use unit_can_airlift_to(). */
162 if (!GOTO
&& !pCity
->airlift
) {
166 fc_snprintf(cBuf
, sizeof(cBuf
), "%s (%d)", city_name_get(pCity
),
167 city_size_get(pCity
));
169 pstr
= create_utf8_from_char(cBuf
, adj_font(12));
170 pstr
->style
|= TTF_STYLE_BOLD
;
172 if (!player_owns_city(owner
, pCity
)) {
173 pLogo
= get_nation_flag_surface(nation_of_player(city_owner(pCity
)));
174 pLogo
= crop_visible_part_from_surface(pLogo
);
177 pBuf
= create_iconlabel(pLogo
, pGotoDlg
->pEndWidgetList
->dst
, pstr
,
178 (WF_RESTORE_BACKGROUND
|WF_DRAW_TEXT_LABEL_WITH_SPACE
));
180 if (!player_owns_city(owner
, pCity
)) {
181 set_wflag(pBuf
, WF_FREE_THEME
);
182 owner
= city_owner(pCity
);
185 pBuf
->string_utf8
->fgcol
=
186 *(get_player_color(tileset
, city_owner(pCity
))->color
);
187 pBuf
->action
= goto_city_callback
;
189 if (GOTO
|| pCity
->airlift
) {
190 set_wstate(pBuf
, FC_WS_NORMAL
);
193 fc_assert((MAX_ID
- pCity
->id
) > 0);
194 pBuf
->ID
= MAX_ID
- pCity
->id
;
196 DownAdd(pBuf
, pAdd_Dock
);
199 if (n
> (pGotoDlg
->pScroll
->active
- 1)) {
200 set_wflag(pBuf
, WF_HIDDEN
);
204 } city_list_iterate_end
;
205 } players_iterate_end
;
208 pGotoDlg
->pBeginWidgetList
= pBuf
;
210 pGotoDlg
->pBeginActiveWidgetList
= pGotoDlg
->pBeginWidgetList
;
211 pGotoDlg
->pEndActiveWidgetList
= pLast
->prev
;
212 pGotoDlg
->pActiveWidgetList
= pGotoDlg
->pEndActiveWidgetList
;
213 pGotoDlg
->pScroll
->count
= n
;
215 if (n
> pGotoDlg
->pScroll
->active
) {
216 show_scrollbar(pGotoDlg
->pScroll
);
217 pGotoDlg
->pScroll
->pScrollBar
->size
.y
= pGotoDlg
->pEndWidgetList
->area
.y
+
218 pGotoDlg
->pScroll
->pUp_Left_Button
->size
.h
;
219 pGotoDlg
->pScroll
->pScrollBar
->size
.h
= scrollbar_size(pGotoDlg
->pScroll
);
221 hide_scrollbar(pGotoDlg
->pScroll
);
224 setup_vertical_widgets_position(1,
225 pGotoDlg
->pEndWidgetList
->area
.x
,
226 pGotoDlg
->pEndWidgetList
->area
.y
,
227 pGotoDlg
->pScroll
->pUp_Left_Button
->size
.x
-
228 pGotoDlg
->pEndWidgetList
->area
.x
- adj_size(2),
229 0, pGotoDlg
->pBeginActiveWidgetList
,
230 pGotoDlg
->pEndActiveWidgetList
);
233 hide_scrollbar(pGotoDlg
->pScroll
);
237 redraw_group(pGotoDlg
->pBeginWidgetList
, pGotoDlg
->pEndWidgetList
, 0);
238 widget_flush(pGotoDlg
->pEndWidgetList
);
241 /**************************************************************************
242 Popup a dialog to have the focus unit goto to a city.
243 **************************************************************************/
244 static void popup_goto_airlift_dialog(void)
246 SDL_Color bg_color
= {0, 0, 0, 96};
247 struct widget
*pBuf
, *pWindow
;
249 SDL_Surface
*pFlag
, *pEnabled
, *pDisabled
;
251 int i
, col
, block_x
, x
, y
;
258 pGotoDlg
= fc_calloc(1, sizeof(struct ADVANCED_DLG
));
260 pstr
= create_utf8_from_char(_("Select destination"), adj_font(12));
261 pstr
->style
|= TTF_STYLE_BOLD
;
263 pWindow
= create_window_skeleton(NULL
, pstr
, 0);
265 pWindow
->action
= goto_dialog_window_callback
;
266 set_wstate(pWindow
, FC_WS_NORMAL
);
268 add_to_gui_list(ID_WINDOW
, pWindow
);
269 pGotoDlg
->pEndWidgetList
= pWindow
;
271 area
= pWindow
->area
;
274 /* create exit button */
275 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
276 WF_WIDGET_HAS_INFO_LABEL
| WF_RESTORE_BACKGROUND
);
277 pBuf
->info_label
= create_utf8_from_char(_("Close Dialog (Esc)"),
279 pBuf
->action
= exit_goto_dialog_callback
;
280 set_wstate(pBuf
, FC_WS_NORMAL
);
281 pBuf
->key
= SDLK_ESCAPE
;
282 area
.w
= MAX(area
.w
, pBuf
->size
.w
) + adj_size(10);
284 add_to_gui_list(ID_BUTTON
, pBuf
);
287 /* --------------------------------------------- */
288 players_iterate(pPlayer
) {
289 if (pPlayer
!= client
.conn
.playing
290 && DS_NO_CONTACT
== player_diplstate_get(client
.conn
.playing
, pPlayer
)->type
) {
294 pFlag
= ResizeSurfaceBox(get_nation_flag_surface(pPlayer
->nation
),
295 adj_size(30), adj_size(30), 1, TRUE
, FALSE
);
297 pEnabled
= create_icon_theme_surf(pFlag
);
298 fill_rect_alpha(pFlag
, NULL
, &bg_color
);
299 pDisabled
= create_icon_theme_surf(pFlag
);
302 pBuf
= create_checkbox(pWindow
->dst
,
303 BV_ISSET(all_players
, player_index(pPlayer
)),
304 WF_FREE_THEME
| WF_RESTORE_BACKGROUND
305 | WF_WIDGET_HAS_INFO_LABEL
);
306 set_new_checkbox_theme(pBuf
, pEnabled
, pDisabled
);
309 create_utf8_from_char(nation_adjective_for_player(pPlayer
),
311 pBuf
->info_label
->style
&= ~SF_CENTER
;
312 set_wstate(pBuf
, FC_WS_NORMAL
);
314 pBuf
->action
= toggle_goto_nations_cities_dialog_callback
;
315 add_to_gui_list(MAX_ID
- player_number(pPlayer
), pBuf
);
317 } players_iterate_end
;
319 pGotoDlg
->pBeginWidgetList
= pBuf
;
321 create_vertical_scrollbar(pGotoDlg
, 1, adj_size(320) / adj_size(30), TRUE
, TRUE
);
322 hide_scrollbar(pGotoDlg
->pScroll
);
324 area
.w
= MAX(area
.w
, adj_size(300));
325 area
.h
= adj_size(320);
327 resize_window(pWindow
, NULL
, NULL
,
328 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
329 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
);
332 col
= (col
+ 15) / 16; /* number of flag columns */
334 pFlag
= ResizeSurface(current_theme
->Block
,
335 (col
* pBuf
->size
.w
+ (col
- 1) * adj_size(5) + adj_size(10)),
338 block_x
= dst
.x
= area
.x
+ area
.w
- pFlag
->w
;
340 alphablit(pFlag
, NULL
, pWindow
->theme
, &dst
, 255);
343 widget_set_position(pWindow
,
344 (main_window_width() - pWindow
->size
.w
) / 2,
345 (main_window_height() - pWindow
->size
.h
) / 2);
348 pBuf
= pWindow
->prev
;
349 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
350 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
352 /* nations buttons */
355 x
= block_x
+ adj_size(5);
356 y
= area
.y
+ adj_size(1);
361 if (!((i
+ 1) % col
)) {
362 x
= block_x
+ adj_size(5);
363 y
+= pBuf
->size
.h
+ adj_size(1);
365 x
+= pBuf
->size
.w
+ adj_size(5);
368 if (pBuf
== pGotoDlg
->pBeginWidgetList
) {
376 setup_vertical_scrollbar_area(pGotoDlg
->pScroll
,
380 update_goto_dialog();
384 /**************************************************************************
385 Popup a dialog to have the focus unit goto to a city.
386 **************************************************************************/
387 void popup_goto_dialog(void)
389 if (!can_client_issue_orders() || 0 == get_num_units_in_focus()) {
393 BV_CLR_ALL(all_players
);
394 BV_SET(all_players
, player_index(client
.conn
.playing
));
395 /* FIXME: Should we include allies in all_players */
396 popup_goto_airlift_dialog();
399 /**************************************************************************
400 Popup a dialog to have the focus unit airlift to a city.
401 **************************************************************************/
402 void popup_airlift_dialog(void)
404 if (!can_client_issue_orders() || 0 == get_num_units_in_focus()) {
408 BV_CLR_ALL(all_players
);
409 BV_SET(all_players
, player_index(client
.conn
.playing
));
410 /* FIXME: Should we include allies in all_players */
412 popup_goto_airlift_dialog();
415 /**************************************************************************
416 Popdown goto/airlift to a city dialog.
417 **************************************************************************/
418 void popdown_goto_airlift_dialog(void)
421 popdown_window_group_dialog(pGotoDlg
->pBeginWidgetList
,
422 pGotoDlg
->pEndWidgetList
);
423 FC_FREE(pGotoDlg
->pScroll
);