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)
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 /* utility */
19 #include "fcintl.h"
20 #include "log.h"
21 
22 /* common */
23 #include "game.h"
24 #include "packets.h"
25 #include "victory.h"
26 
27 /* client */
28 #include "client_main.h"
29 #include "text.h"
30 
31 /* gui-sdl */
32 #include "graphics.h"
33 #include "gui_id.h"
34 #include "gui_main.h"
35 #include "gui_tilespec.h"
36 #include "mapview.h"
37 #include "widget.h"
38 
39 #include "spaceshipdlg.h"
40 
41 #define SPECLIST_TAG dialog
42 #define SPECLIST_TYPE struct SMALL_DLG
43 #include "speclist.h"
44 
45 #define dialog_list_iterate(dialoglist, pdialog) \
46     TYPED_LIST_ITERATE(struct SMALL_DLG, dialoglist, pdialog)
47 #define dialog_list_iterate_end  LIST_ITERATE_END
48 
49 static struct dialog_list *dialog_list = NULL;
50 static bool dialog_list_has_been_initialised = FALSE;
51 
52 /****************************************************************
53 ...
54 *****************************************************************/
get_spaceship_dialog(struct player * pplayer)55 static struct SMALL_DLG *get_spaceship_dialog(struct player *pplayer)
56 {
57   if (!dialog_list_has_been_initialised) {
58     dialog_list = dialog_list_new();
59     dialog_list_has_been_initialised = TRUE;
60   }
61 
62   dialog_list_iterate(dialog_list, pDialog) {
63     if (pDialog->pEndWidgetList->data.player == pplayer) {
64       return pDialog;
65     }
66   } dialog_list_iterate_end;
67 
68   return NULL;
69 }
70 
space_dialog_window_callback(struct widget * pWindow)71 static int space_dialog_window_callback(struct widget *pWindow)
72 {
73   if (Main.event.button.button == SDL_BUTTON_LEFT) {
74     move_window_group(pWindow->private_data.small_dlg->pBeginWidgetList, pWindow);
75   }
76   return -1;
77 }
78 
exit_space_dialog_callback(struct widget * pWidget)79 static int exit_space_dialog_callback(struct widget *pWidget)
80 {
81   if (Main.event.button.button == SDL_BUTTON_LEFT) {
82     popdown_spaceship_dialog(pWidget->data.player);
83     flush_dirty();
84   }
85   return -1;
86 }
87 
launch_spaceship_callback(struct widget * pWidget)88 static int launch_spaceship_callback(struct widget *pWidget)
89 {
90   if (Main.event.button.button == SDL_BUTTON_LEFT) {
91     send_packet_spaceship_launch(&client.conn);
92   }
93   return -1;
94 }
95 
96 /**************************************************************************
97   Refresh (update) the spaceship dialog for the given player.
98 **************************************************************************/
refresh_spaceship_dialog(struct player * pPlayer)99 void refresh_spaceship_dialog(struct player *pPlayer)
100 {
101   struct SMALL_DLG *pSpaceShp;
102   struct widget *pBuf;
103 
104   if (!(pSpaceShp = get_spaceship_dialog(pPlayer))) {
105     return;
106   }
107 
108   /* launch button */
109   pBuf = pSpaceShp->pEndWidgetList->prev->prev;
110   if (victory_enabled(VC_SPACERACE)
111       && pPlayer == client.conn.playing
112       && pPlayer->spaceship.state == SSHIP_STARTED
113       && pPlayer->spaceship.success_rate > 0.0) {
114     set_wstate(pBuf, FC_WS_NORMAL);
115   }
116 
117   /* update text info */
118   pBuf = pBuf->prev;
119   copy_chars_to_string16(pBuf->string16,
120 				get_spaceship_descr(&pPlayer->spaceship));
121   /* ------------------------------------------ */
122 
123     /* redraw */
124   redraw_group(pSpaceShp->pBeginWidgetList, pSpaceShp->pEndWidgetList, 0);
125   widget_mark_dirty(pSpaceShp->pEndWidgetList);
126 
127   flush_dirty();
128 }
129 
130 /**************************************************************************
131   Popup (or raise) the spaceship dialog for the given player.
132 **************************************************************************/
popup_spaceship_dialog(struct player * pPlayer)133 void popup_spaceship_dialog(struct player *pPlayer)
134 {
135   struct SMALL_DLG *pSpaceShp;
136 
137   if(!(pSpaceShp = get_spaceship_dialog(pPlayer))) {
138     struct widget *pBuf, *pWindow;
139     SDL_String16 *pStr;
140     char cBuf[128];
141     SDL_Rect area;
142 
143     pSpaceShp = fc_calloc(1, sizeof(struct SMALL_DLG));
144 
145     fc_snprintf(cBuf, sizeof(cBuf), _("The %s Spaceship"),
146 				    nation_adjective_for_player(pPlayer));
147     pStr = create_str16_from_char(cBuf, adj_font(12));
148     pStr->style |= TTF_STYLE_BOLD;
149 
150     pWindow = create_window_skeleton(NULL, pStr, 0);
151 
152     pWindow->action = space_dialog_window_callback;
153     set_wstate(pWindow, FC_WS_NORMAL);
154     pWindow->data.player = pPlayer;
155     pWindow->private_data.small_dlg = pSpaceShp;
156     add_to_gui_list(ID_WINDOW, pWindow);
157     pSpaceShp->pEndWidgetList = pWindow;
158 
159     area = pWindow->area;
160 
161     /* ---------- */
162     /* create exit button */
163     pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
164                             WF_WIDGET_HAS_INFO_LABEL
165                             | WF_RESTORE_BACKGROUND);
166     pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
167                                               adj_font(12));
168     pBuf->data.player = pPlayer;
169     pBuf->action = exit_space_dialog_callback;
170     set_wstate(pBuf, FC_WS_NORMAL);
171     pBuf->key = SDLK_ESCAPE;
172     area.w = MAX(area.w, (pBuf->size.w + adj_size(10)));
173 
174     add_to_gui_list(ID_BUTTON, pBuf);
175 
176     pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
177                                               _("Launch"), adj_font(12), 0);
178 
179     pBuf->action = launch_spaceship_callback;
180     area.w = MAX(area.w, pBuf->size.w);
181     area.h += pBuf->size.h + adj_size(20);
182     add_to_gui_list(ID_BUTTON, pBuf);
183 
184     pStr = create_str16_from_char(get_spaceship_descr(NULL), adj_font(12));
185     pStr->bgcol = (SDL_Color) {0, 0, 0, 0};
186     pBuf = create_iconlabel(NULL, pWindow->dst, pStr, WF_RESTORE_BACKGROUND);
187     area.w = MAX(area.w, pBuf->size.w);
188     area.h += pBuf->size.h + adj_size(20);
189     add_to_gui_list(ID_LABEL, pBuf);
190 
191     pSpaceShp->pBeginWidgetList = pBuf;
192     /* -------------------------------------------------------- */
193 
194     area.w = MAX(area.w, adj_size(300) - (pWindow->size.w - pWindow->area.w));
195 
196     resize_window(pWindow, NULL, NULL,
197                   (pWindow->size.w - pWindow->area.w) + area.w,
198                   (pWindow->size.h - pWindow->area.h) + area.h);
199 
200     area = pWindow->area;
201 
202     widget_set_position(pWindow,
203                         (Main.screen->w - pWindow->size.w) / 2,
204                         (Main.screen->h - pWindow->size.h) / 2);
205 
206     /* exit button */
207     pBuf = pWindow->prev;
208     pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
209     pBuf->size.y = pWindow->size.y + adj_size(2);
210 
211     /* launch button */
212     pBuf = pBuf->prev;
213     pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
214     pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
215 
216     /* info label */
217     pBuf = pBuf->prev;
218     pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
219     pBuf->size.y = area.y + adj_size(7);
220 
221     dialog_list_prepend(dialog_list, pSpaceShp);
222 
223     refresh_spaceship_dialog(pPlayer);
224   } else {
225     if (sellect_window_group_dialog(pSpaceShp->pBeginWidgetList,
226 				   pSpaceShp->pEndWidgetList)) {
227       widget_flush(pSpaceShp->pEndWidgetList);
228     }
229   }
230 
231 }
232 
233 /**************************************************************************
234   Close the spaceship dialog for the given player.
235 **************************************************************************/
popdown_spaceship_dialog(struct player * pPlayer)236 void popdown_spaceship_dialog(struct player *pPlayer)
237 {
238   struct SMALL_DLG *pSpaceShp;
239 
240   if((pSpaceShp = get_spaceship_dialog(pPlayer))) {
241     popdown_window_group_dialog(pSpaceShp->pBeginWidgetList,
242 					    pSpaceShp->pEndWidgetList);
243     dialog_list_remove(dialog_list, pSpaceShp);
244     FC_FREE(pSpaceShp);
245   }
246 
247 }
248