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>
29 /* client/gui-gtk-2.0 */
33 #include "voteinfo_bar.h"
35 /* A set of widgets. */
38 GtkWidget
*next_button
;
40 GtkWidget
*yes_button
;
42 GtkWidget
*abstain_button
;
43 GtkWidget
*yes_count_label
;
44 GtkWidget
*no_count_label
;
45 GtkWidget
*abstain_count_label
;
46 GtkWidget
*voter_count_label
;
49 GtkWidget
*pregame_votebar
= NULL
; /* PAGE_START voteinfo bar. */
50 GtkWidget
*ingame_votebar
= NULL
; /* PAGE_GAME voteinfo bar. */
52 /**************************************************************************
53 Called after a click on a vote button.
54 **************************************************************************/
55 static void voteinfo_bar_do_vote_callback(GtkWidget
*w
, gpointer userdata
)
57 enum client_vote_type vote
;
60 vote
= GPOINTER_TO_INT(userdata
);
61 vi
= voteinfo_queue_get_current(NULL
);
67 voteinfo_do_vote(vi
->vote_no
, vote
);
70 /**************************************************************************
71 Switch to the next vote.
72 **************************************************************************/
73 static void voteinfo_bar_next_callback(GtkWidget
*w
, gpointer userdata
)
75 voteinfo_queue_next();
76 voteinfo_gui_update();
79 /**************************************************************************
80 Destroy the voteinfo_bar data structure.
81 **************************************************************************/
82 static void voteinfo_bar_destroy(GtkWidget
*w
, gpointer userdata
)
84 free((struct voteinfo_bar
*) userdata
);
87 /**************************************************************************
88 Create a voteinfo_bar structure. "split_bar" controls whether to split
89 voteinfo bar over two lines (for narrow windows) or put on a single line
90 to save vertical space.
91 **************************************************************************/
92 GtkWidget
*voteinfo_bar_new(bool split_bar
)
94 GtkWidget
*label
, *button
, *vbox
, *hbox
, *evbox
, *spacer
, *arrow
;
95 struct voteinfo_bar
*vib
;
96 const int BUTTON_HEIGHT
= 12;
98 vib
= fc_calloc(1, sizeof(struct voteinfo_bar
));
101 hbox
= gtk_hbox_new(FALSE
, 4);
102 g_object_set_data(G_OBJECT(hbox
), "voteinfo_bar", vib
);
103 g_signal_connect(hbox
, "destroy", G_CALLBACK(voteinfo_bar_destroy
), vib
);
105 vbox
= NULL
; /* The compiler may require it. */
107 vbox
= gtk_vbox_new(TRUE
, 4);
108 g_object_set_data(G_OBJECT(vbox
), "voteinfo_bar", vib
);
109 g_signal_connect(vbox
, "destroy", G_CALLBACK(voteinfo_bar_destroy
), vib
);
111 hbox
= gtk_hbox_new(FALSE
, 4);
112 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
115 label
= gtk_label_new("");
116 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
117 gtk_misc_set_padding(GTK_MISC(label
), 8, 4);
118 gtk_label_set_max_width_chars(GTK_LABEL(label
), 80);
119 evbox
= gtk_event_box_new();
120 gtk_container_add(GTK_CONTAINER(evbox
), label
);
121 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, TRUE
, TRUE
, 0);
122 gtk_widget_set_name(evbox
, "vote label");
125 arrow
= gtk_image_new_from_stock(GTK_STOCK_MEDIA_REWIND
,
126 GTK_ICON_SIZE_SMALL_TOOLBAR
);
127 gtk_misc_set_alignment(GTK_MISC(arrow
), 0.5, 0.25);
130 hbox
= gtk_hbox_new(FALSE
, 4);
131 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, TRUE
, 0);
134 button
= gtk_button_new();
135 g_signal_connect(button
, "clicked",
136 G_CALLBACK(voteinfo_bar_next_callback
), NULL
);
137 gtk_button_set_image(GTK_BUTTON(button
), arrow
);
138 gtk_widget_set_size_request(button
, -1, BUTTON_HEIGHT
);
139 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
140 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
141 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
142 vib
->next_button
= button
;
144 spacer
= gtk_alignment_new(0, 0, 0, 0);
145 gtk_widget_set_size_request(spacer
, 16, -1);
146 gtk_box_pack_start(GTK_BOX(hbox
), spacer
, FALSE
, FALSE
, 0);
148 button
= gtk_button_new_with_mnemonic(_("_YES"));
149 g_signal_connect(button
, "clicked",
150 G_CALLBACK(voteinfo_bar_do_vote_callback
),
151 GINT_TO_POINTER(CVT_YES
));
152 gtk_widget_set_size_request(button
, 50, BUTTON_HEIGHT
);
153 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
154 evbox
= gtk_event_box_new();
155 gtk_container_add(GTK_CONTAINER(evbox
), button
);
156 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, FALSE
, FALSE
, 0);
157 gtk_widget_set_name(button
, "vote yes button");
158 gtk_widget_set_name(evbox
, "vote yes button");
159 gtk_widget_set_name(gtk_bin_get_child(GTK_BIN(button
)),
161 vib
->yes_button
= button
;
163 label
= gtk_label_new("0");
164 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
165 gtk_widget_set_size_request(label
, 24, -1);
166 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
167 vib
->yes_count_label
= label
;
169 button
= gtk_button_new_with_mnemonic(_("_NO"));
170 g_signal_connect(button
, "clicked",
171 G_CALLBACK(voteinfo_bar_do_vote_callback
),
172 GINT_TO_POINTER(CVT_NO
));
173 gtk_widget_set_size_request(button
, 50, BUTTON_HEIGHT
);
174 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
175 evbox
= gtk_event_box_new();
176 gtk_container_add(GTK_CONTAINER(evbox
), button
);
177 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, FALSE
, FALSE
, 0);
178 gtk_widget_set_name(button
, "vote no button");
179 gtk_widget_set_name(evbox
, "vote no button");
180 gtk_widget_set_name(gtk_bin_get_child(GTK_BIN(button
)),
182 vib
->no_button
= button
;
184 label
= gtk_label_new("0");
185 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
186 gtk_widget_set_size_request(label
, 24, -1);
187 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
188 vib
->no_count_label
= label
;
190 button
= gtk_button_new_with_mnemonic(_("_ABSTAIN"));
191 g_signal_connect(button
, "clicked",
192 G_CALLBACK(voteinfo_bar_do_vote_callback
),
193 GINT_TO_POINTER(CVT_ABSTAIN
));
194 gtk_widget_set_size_request(button
, 50, BUTTON_HEIGHT
);
195 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
196 evbox
= gtk_event_box_new();
197 gtk_container_add(GTK_CONTAINER(evbox
), button
);
198 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, FALSE
, FALSE
, 0);
199 gtk_widget_set_name(button
, "vote abstain button");
200 gtk_widget_set_name(evbox
, "vote abstain button");
201 gtk_widget_set_name(gtk_bin_get_child(GTK_BIN(button
)),
202 "vote abstain button");
203 vib
->abstain_button
= button
;
205 label
= gtk_label_new("0");
206 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
207 gtk_widget_set_size_request(label
, 24, -1);
208 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
209 vib
->abstain_count_label
= label
;
211 label
= gtk_label_new("/0");
212 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
213 gtk_widget_set_size_request(label
, 24, -1);
214 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
215 vib
->voter_count_label
= label
;
220 /****************************************************************************
221 Refresh all vote related GUI widgets. Called by the voteinfo module when
222 the client receives new vote information from the server.
223 ****************************************************************************/
224 void voteinfo_gui_update(void)
226 int vote_count
, index
;
227 struct voteinfo_bar
*vib
= NULL
;
228 struct voteinfo
*vi
= NULL
;
229 char buf
[1024], status
[1024], ordstr
[128], color
[32];
230 bool running
, need_scroll
;
231 gchar
*escaped_desc
, *escaped_user
;
233 if (get_client_page() == PAGE_START
&& NULL
!= pregame_votebar
) {
234 vib
= g_object_get_data(G_OBJECT(pregame_votebar
), "voteinfo_bar");
235 } else if (get_client_page() == PAGE_GAME
&& NULL
!= ingame_votebar
) {
236 vib
= g_object_get_data(G_OBJECT(ingame_votebar
), "voteinfo_bar");
243 if (!voteinfo_bar_can_be_shown()) {
244 gtk_widget_hide_all(vib
->box
);
248 vote_count
= voteinfo_queue_size();
249 vi
= voteinfo_queue_get_current(&index
);
251 if (vi
!= NULL
&& vi
->resolved
&& vi
->passed
) {
252 /* TRANS: Describing a vote that passed. */
253 fc_snprintf(status
, sizeof(status
), _("[passed]"));
254 sz_strlcpy(color
, "green");
255 } else if (vi
!= NULL
&& vi
->resolved
&& !vi
->passed
) {
256 /* TRANS: Describing a vote that failed. */
257 fc_snprintf(status
, sizeof(status
), _("[failed]"));
258 sz_strlcpy(color
, "red");
259 } else if (vi
!= NULL
&& vi
->remove_time
> 0) {
260 /* TRANS: Describing a vote that was removed. */
261 fc_snprintf(status
, sizeof(status
), _("[removed]"));
262 sz_strlcpy(color
, "grey");
267 if (vote_count
> 1) {
268 fc_snprintf(ordstr
, sizeof(ordstr
),
269 "<span weight=\"bold\">(%d/%d)</span> ",
270 index
+ 1, vote_count
);
275 if (status
[0] != '\0') {
276 fc_snprintf(buf
, sizeof(buf
),
277 "<span weight=\"bold\" background=\"%s\">%s</span> ",
279 sz_strlcpy(status
, buf
);
283 escaped_desc
= g_markup_escape_text(vi
->desc
, -1);
284 escaped_user
= g_markup_escape_text(vi
->user
, -1);
285 /* TRANS: "Vote" as a process */
286 fc_snprintf(buf
, sizeof(buf
), _("%sVote %d by %s: %s%s"),
287 ordstr
, vi
->vote_no
, escaped_user
, status
,
289 g_free(escaped_desc
);
290 g_free(escaped_user
);
294 gtk_label_set_markup(GTK_LABEL(vib
->label
), buf
);
297 fc_snprintf(buf
, sizeof(buf
), "%d", vi
->yes
);
298 gtk_label_set_text(GTK_LABEL(vib
->yes_count_label
), buf
);
299 fc_snprintf(buf
, sizeof(buf
), "%d", vi
->no
);
300 gtk_label_set_text(GTK_LABEL(vib
->no_count_label
), buf
);
301 fc_snprintf(buf
, sizeof(buf
), "%d", vi
->abstain
);
302 gtk_label_set_text(GTK_LABEL(vib
->abstain_count_label
), buf
);
303 fc_snprintf(buf
, sizeof(buf
), "/%d", vi
->num_voters
);
304 gtk_label_set_text(GTK_LABEL(vib
->voter_count_label
), buf
);
306 gtk_label_set_text(GTK_LABEL(vib
->yes_count_label
), "-");
307 gtk_label_set_text(GTK_LABEL(vib
->no_count_label
), "-");
308 gtk_label_set_text(GTK_LABEL(vib
->abstain_count_label
), "-");
309 gtk_label_set_text(GTK_LABEL(vib
->voter_count_label
), "/-");
312 running
= vi
!= NULL
&& !vi
->resolved
&& vi
->remove_time
== 0;
314 gtk_widget_set_sensitive(vib
->yes_button
, running
);
315 gtk_widget_set_sensitive(vib
->no_button
, running
);
316 gtk_widget_set_sensitive(vib
->abstain_button
, running
);
318 need_scroll
= !GTK_WIDGET_VISIBLE(vib
->box
)
319 && chatline_is_scrolled_to_bottom();
321 gtk_widget_show_all(vib
->box
);
323 if (vote_count
<= 1) {
324 gtk_widget_hide(vib
->next_button
);
328 /* Showing the votebar when it was hidden
329 * previously makes the chatline scroll up. */
330 chatline_scroll_to_bottom(TRUE
);