Qt client - remove right click menu from end turn sidebar
[freeciv.git] / client / gui-gtk-2.0 / voteinfo_bar.c
blob8a368eb6dc57a83971721af02236e0d16e5d1a73
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.
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 #include <gtk/gtk.h>
20 /* utility */
21 #include "fcintl.h"
22 #include "mem.h"
23 #include "support.h"
25 /* client */
26 #include "options.h"
27 #include "voteinfo.h"
29 /* client/gui-gtk-2.0 */
30 #include "chatline.h"
31 #include "pages.h"
33 #include "voteinfo_bar.h"
35 /* A set of widgets. */
36 struct voteinfo_bar {
37 GtkWidget *box;
38 GtkWidget *next_button;
39 GtkWidget *label;
40 GtkWidget *yes_button;
41 GtkWidget *no_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;
58 struct voteinfo *vi;
60 vote = GPOINTER_TO_INT(userdata);
61 vi = voteinfo_queue_get_current(NULL);
63 if (vi == NULL) {
64 return;
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));
100 if (!split_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);
104 vib->box = hbox;
105 vbox = NULL; /* The compiler may require it. */
106 } else {
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);
110 vib->box = vbox;
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");
123 vib->label = 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);
129 if (split_bar) {
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)),
160 "vote yes 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)),
181 "vote no 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;
217 return vib->box;
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");
239 if (vib == NULL) {
240 return;
243 if (!voteinfo_bar_can_be_shown()) {
244 gtk_widget_hide_all(vib->box);
245 return;
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");
263 } else {
264 status[0] = '\0';
267 if (vote_count > 1) {
268 fc_snprintf(ordstr, sizeof(ordstr),
269 "<span weight=\"bold\">(%d/%d)</span> ",
270 index + 1, vote_count);
271 } else {
272 ordstr[0] = '\0';
275 if (status[0] != '\0') {
276 fc_snprintf(buf, sizeof(buf),
277 "<span weight=\"bold\" background=\"%s\">%s</span> ",
278 color, status);
279 sz_strlcpy(status, buf);
282 if (vi != NULL) {
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,
288 escaped_desc);
289 g_free(escaped_desc);
290 g_free(escaped_user);
291 } else {
292 buf[0] = '\0';
294 gtk_label_set_markup(GTK_LABEL(vib->label), buf);
296 if (vi != NULL) {
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);
305 } else {
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);
327 if (need_scroll) {
328 /* Showing the votebar when it was hidden
329 * previously makes the chatline scroll up. */
330 chatline_scroll_to_bottom(TRUE);