Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-3.0/gui_main.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
gui_main.c
Go to the documentation of this file.
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#ifdef AUDIO_SDL
19/* Though it would happily compile without this include,
20 * it is needed for sound to work.
21 * It defines "main" macro to rename our main() so that
22 * it can install SDL's own. */
23#ifdef SDL2_PLAIN_INCLUDE
24#include <SDL.h>
25#else /* PLAIN_INCLUDE */
26#include <SDL2/SDL.h>
27#endif /* PLAIN_INCLUDE */
28#endif /* AUDIO_SDL */
29
30#ifdef HAVE_LOCALE_H
31#include <locale.h>
32#endif
33#include <stdarg.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <time.h>
38
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43#include <gtk/gtk.h>
44#include <gdk/gdkkeysyms.h>
45
46/* utility */
47#include "fc_cmdline.h"
48#include "fciconv.h"
49#include "fcintl.h"
50#include "log.h"
51#include "mem.h"
52#include "support.h"
53
54/* common */
55#include "dataio.h"
56#include "featured_text.h"
57#include "game.h"
58#include "government.h"
59#include "map.h"
60#include "unitlist.h"
61#include "version.h"
62
63/* client */
64#include "client_main.h"
65#include "climisc.h"
66#include "clinet.h"
67#include "colors.h"
68#include "connectdlg_common.h"
69#include "control.h"
70#include "editor.h"
71#include "options.h"
72#include "text.h"
73#include "tilespec.h"
74#include "zoom.h"
75
76/* client/gui-gtk-3.0 */
77#include "chatline.h"
78#include "citizensinfo.h"
79#include "connectdlg.h"
80#include "cma_fe.h"
81#include "dialogs.h"
82#include "diplodlg.h"
83#include "editgui.h"
84#include "gotodlg.h"
85#include "graphics.h"
86#include "gui_stuff.h"
87#include "happiness.h"
88#include "helpdlg.h"
89#include "inteldlg.h"
90#include "mapctrl.h"
91#include "mapview.h"
92#include "menu.h"
93#include "messagewin.h"
94#include "optiondlg.h"
95#include "pages.h"
96#include "plrdlg.h"
97#include "luaconsole.h"
98#include "spaceshipdlg.h"
99#include "repodlgs.h"
100#include "voteinfo_bar.h"
101
102#include "gui_main.h"
103
104 const char *client_string = GUI_NAME_FULL;
105
106GtkWidget *map_canvas; /* GtkDrawingArea */
107GtkWidget *map_horizontal_scrollbar;
108GtkWidget *map_vertical_scrollbar;
109
110GtkWidget *overview_canvas; /* GtkDrawingArea */
111GtkWidget *overview_scrolled_window; /* GtkScrolledWindow */
112/* The two values below define the width and height of the map overview. The
113 * first set of values (2*62, 2*46) define the size for a netbook display. For
114 * bigger displays the values are doubled (default). */
115#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK (2 * 64)
116#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK (2 * 46)
117#define OVERVIEW_CANVAS_STORE_WIDTH \
118 (2 * OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK)
119#define OVERVIEW_CANVAS_STORE_HEIGHT \
120 (2 * OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK)
121 int overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
122 int overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
123
124GtkWidget *toplevel;
125GdkWindow *root_window;
126GtkWidget *toplevel_tabs;
127GtkWidget *top_vbox;
128GtkWidget *top_notebook, *bottom_notebook, *right_notebook;
129GtkWidget *map_widget;
130 static GtkWidget *bottom_hpaned;
131
132PangoFontDescription *city_names_style = NULL;
133PangoFontDescription *city_productions_style = NULL;
134PangoFontDescription *reqtree_text_style = NULL;
135
136GtkWidget *main_frame_civ_name;
137GtkWidget *main_label_info;
138
139GtkWidget *avbox, *ahbox, *conn_box;
140GtkWidget* scroll_panel;
141
142GtkWidget *econ_label[10];
143GtkWidget *bulb_label;
144GtkWidget *sun_label;
145GtkWidget *flake_label;
146GtkWidget *government_label;
147GtkWidget *timeout_label;
148GtkWidget *turn_done_button;
149
150GtkWidget *unit_info_label;
151GtkWidget *unit_info_box;
152GtkWidget *unit_info_frame;
153
154GtkWidget *econ_ebox;
155GtkWidget *bulb_ebox;
156GtkWidget *sun_ebox;
157GtkWidget *flake_ebox;
158GtkWidget *government_ebox;
159
160 const char *const gui_character_encoding = "UTF-8";
161 const bool gui_use_transliteration = FALSE;
162
163 static GtkWidget *main_menubar;
164 static GtkWidget *unit_image_table;
165 static GtkWidget *unit_image;
166 static GtkWidget *unit_image_button;
167 static GtkWidget *unit_below_image[MAX_NUM_UNITS_BELOW];
168 static GtkWidget *unit_below_image_button[MAX_NUM_UNITS_BELOW];
169 static GtkWidget *more_arrow_pixmap;
170 static GtkWidget *more_arrow_pixmap_button;
171 static GtkWidget *more_arrow_pixmap_container;
172
173 static int unit_id_top;
174 static int unit_ids[MAX_NUM_UNITS_BELOW]; /* ids of the units icons in
175 * information display: (or 0) */
176GtkTextView *main_message_area;
177GtkTextBuffer *message_buffer = NULL;
178 static GtkWidget *allied_chat_toggle_button;
179
180 static gint timer_id; /* ditto */
181 static GIOChannel *srv_channel;
182 static guint srv_id;
183gint cur_x, cur_y;
184
185 static bool gui_up = FALSE;
186
187 static struct video_mode vmode = { -1, -1 };
188
189static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data);
190static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data);
191
192static void end_turn_callback(GtkWidget *w, gpointer data);
193static gboolean get_net_input(GIOChannel *source, GIOCondition condition,
194 gpointer data);
195static void set_wait_for_writable_socket(struct connection *pc,
196 bool socket_writable);
197
198static void print_usage(void);
199static bool parse_options(int argc, char **argv);
200static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data);
201static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev, gpointer data);
202static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev);
203
204static void tearoff_callback(GtkWidget *b, gpointer data);
205static GtkWidget *detached_widget_new(void);
206static GtkWidget *detached_widget_fill(GtkWidget *tearbox);
207
208static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev,
209 gpointer data);
210static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev,
211 gpointer data);
212static gboolean quit_dialog_callback(void);
213
214static void allied_chat_button_toggled(GtkToggleButton *button,
215 gpointer user_data);
216
217static void free_unit_table(void);
218
219static void adjust_default_options(void);
220
221/**********************************************************************/
224 static void log_callback_utf8(enum log_level level, const char *message,
225 bool file_too)
226{
227 if (!file_too || level <= LOG_FATAL) {
228 fc_fprintf(stderr, "%d: %s\n", level, message);
229 }
230}
231
232/**********************************************************************/
236 static gboolean timer_callback(gpointer data)
237{
238 double seconds = real_timer_callback();
239
240 timer_id = g_timeout_add(seconds * 1000, timer_callback, NULL);
241
242 return FALSE;
243}
244
245/**********************************************************************/
249 static void print_usage(void)
250{
251 /* add client-specific usage information here */
252 fc_fprintf(stderr,
253 _("This client accepts the standard Gtk command-line options\n"
254 "after '--'. See the Gtk documentation.\n\n"));
255
256 fc_fprintf(stderr,
257 _("Other gui-specific options are:\n"));
258
259 fc_fprintf(stderr,
260 _("-g, --gtk-warnings\tAllow Gtk+ to print warnings "
261 "to console\n"));
262
263 fc_fprintf(stderr,
264 _("-r, --resolution WIDTHxHEIGHT\tAssume given resolution "
265 "screen\n"));
266
267 fc_fprintf(stderr, "\n");
268
269 /* TRANS: No full stop after the URL, could cause confusion. */
270 fc_fprintf(stderr, _("Report bugs at %s\n"), BUG_URL);
271}
272
273/**********************************************************************/
276 static void log_gtk_warns(const gchar *log_domain, GLogLevelFlags log_level,
277 const gchar *message,
278 gpointer user_data)
279{
280 log_verbose("%s", message);
281}
282
283/**********************************************************************/
286 static bool parse_options(int argc, char **argv)
287{
288 int i = 1;
289 bool gtk_warns_enabled = FALSE;
290
291 while (i < argc) {
292 char *option = NULL;
293
294 if (is_option("--help", argv[i])) {
295 print_usage();
296
297 return FALSE;
298 } else if (is_option("--gtk-warnings", argv[i])) {
299 gtk_warns_enabled = TRUE;
300 } else if ((option = get_option_malloc("--resolution", argv, &i, argc, FALSE))) {
301 if (!string_to_video_mode(option, &vmode)) {
302 fc_fprintf(stderr, _("Illegal video mode '%s'\n"), option);
303 exit(EXIT_FAILURE);
304 }
305 free(option);
306 }
307 /* Can't check against unknown options, as those might be gtk options */
308
309 i++;
310 }
311
312 if (!gtk_warns_enabled) {
313 g_log_set_handler("Gtk", G_LOG_LEVEL_WARNING, log_gtk_warns, NULL);
314 }
315
316 return TRUE;
317}
318
319/**********************************************************************/
322 static gboolean toplevel_focus(GtkWidget *w, GtkDirectionType arg)
323{
324 switch (arg) {
325 case GTK_DIR_TAB_FORWARD:
326 case GTK_DIR_TAB_BACKWARD:
327
328 if (!gtk_widget_get_can_focus(w)) {
329 return FALSE;
330 }
331
332 if (!gtk_widget_is_focus(w)) {
333 gtk_widget_grab_focus(w);
334 return TRUE;
335 }
336 break;
337
338 default:
339 break;
340 }
341 return FALSE;
342}
343
344/**********************************************************************/
349 static void main_message_area_size_allocate(GtkWidget *widget,
350 GtkAllocation *allocation,
351 gpointer data)
352{
353 static int old_width = 0, old_height = 0;
354
355 if (allocation->width != old_width
356 || allocation->height != old_height) {
357 chatline_scroll_to_bottom(TRUE);
358 old_width = allocation->width;
359 old_height = allocation->height;
360 }
361}
362
363/**********************************************************************/
366gboolean map_canvas_focus(void)
367{
368 gtk_window_present(GTK_WINDOW(toplevel));
369 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
370 gtk_widget_grab_focus(map_canvas);
371 return TRUE;
372}
373
374/**********************************************************************/
383 static gboolean toplevel_handler(GtkWidget *w, GdkEvent *ev, gpointer data)
384{
385 GtkWidget *focus;
386
387 focus = gtk_window_get_focus(GTK_WINDOW(toplevel));
388 if (focus) {
389 if (GTK_IS_ENTRY(focus)
390 || (GTK_IS_TEXT_VIEW(focus)
391 && gtk_text_view_get_editable(GTK_TEXT_VIEW(focus)))) {
392 /* Propagate event to currently focused entry widget. */
393 if (gtk_widget_event(focus, ev)) {
394 /* Do not propagate event to our children. */
395 return TRUE;
396 }
397 }
398 }
399
400 /* Continue propagating event to our children. */
401 return FALSE;
402}
403
404/**********************************************************************/
407 static gboolean key_press_map_canvas(GtkWidget *w, GdkEventKey *ev,
408 gpointer data)
409{
410 if ((ev->state & GDK_SHIFT_MASK)) {
411 switch (ev->keyval) {
412
413 case GDK_KEY_Left:
414 scroll_mapview(DIR8_WEST);
415 return TRUE;
416
417 case GDK_KEY_Right:
418 scroll_mapview(DIR8_EAST);
419 return TRUE;
420
421 case GDK_KEY_Up:
422 scroll_mapview(DIR8_NORTH);
423 return TRUE;
424
425 case GDK_KEY_Down:
426 scroll_mapview(DIR8_SOUTH);
427 return TRUE;
428
429 case GDK_KEY_Home:
430 key_center_capital();
431 return TRUE;
432
433 case GDK_KEY_Page_Up:
434 g_signal_emit_by_name(main_message_area, "move_cursor",
435 GTK_MOVEMENT_PAGES, -1, FALSE);
436 return TRUE;
437
438 case GDK_KEY_Page_Down:
439 g_signal_emit_by_name(main_message_area, "move_cursor",
440 GTK_MOVEMENT_PAGES, 1, FALSE);
441 return TRUE;
442
443 default:
444 break;
445 }
446 } else if (!(ev->state & GDK_CONTROL_MASK)) {
447 switch (ev->keyval) {
448 default:
449 break;
450 }
451 }
452
453 if (ev->state & GDK_SHIFT_MASK) {
454 bool volchange = FALSE;
455
456 switch (ev->keyval) {
457 case GDK_KEY_plus:
458 case GDK_KEY_KP_Add:
459 gui_options.sound_effects_volume += 10;
460 volchange = TRUE;
461 break;
462
463 case GDK_KEY_minus:
464 case GDK_KEY_KP_Subtract:
465 gui_options.sound_effects_volume -= 10;
466 volchange = TRUE;
467 break;
468
469 default:
470 break;
471 }
472
473 if (volchange) {
474 struct option *poption = optset_option_by_name(client_optset, "sound_effects_volume");
475
476 gui_options.sound_effects_volume = CLIP(0, gui_options.sound_effects_volume, 100);
477 option_changed(poption);
478
479 return TRUE;
480 }
481 } else if (!(ev->state & GDK_CONTROL_MASK)) {
482 switch (ev->keyval) {
483 case GDK_KEY_plus:
484 case GDK_KEY_KP_Add:
485 zoom_step_up();
486 return TRUE;
487
488 case GDK_KEY_minus:
489 case GDK_KEY_KP_Subtract:
490 zoom_step_down();
491 return TRUE;
492
493 default:
494 break;
495 }
496 }
497
498 /* Return here if observer */
499 if (client_is_observer()) {
500 return FALSE;
501 }
502
503 switch (ev->keyval) {
504
505 case GDK_KEY_KP_Up:
506 case GDK_KEY_KP_8:
507 case GDK_KEY_Up:
508 case GDK_KEY_8:
509 key_unit_move(DIR8_NORTH);
510 return TRUE;
511
512 case GDK_KEY_KP_Page_Up:
513 case GDK_KEY_KP_9:
514 case GDK_KEY_Page_Up:
515 case GDK_KEY_9:
516 key_unit_move(DIR8_NORTHEAST);
517 return TRUE;
518
519 case GDK_KEY_KP_Right:
520 case GDK_KEY_KP_6:
521 case GDK_KEY_Right:
522 case GDK_KEY_6:
523 key_unit_move(DIR8_EAST);
524 return TRUE;
525
526 case GDK_KEY_KP_Page_Down:
527 case GDK_KEY_KP_3:
528 case GDK_KEY_Page_Down:
529 case GDK_KEY_3:
530 key_unit_move(DIR8_SOUTHEAST);
531 return TRUE;
532
533 case GDK_KEY_KP_Down:
534 case GDK_KEY_KP_2:
535 case GDK_KEY_Down:
536 case GDK_KEY_2:
537 key_unit_move(DIR8_SOUTH);
538 return TRUE;
539
540 case GDK_KEY_KP_End:
541 case GDK_KEY_KP_1:
542 case GDK_KEY_End:
543 case GDK_KEY_1:
544 key_unit_move(DIR8_SOUTHWEST);
545 return TRUE;
546
547 case GDK_KEY_KP_Left:
548 case GDK_KEY_KP_4:
549 case GDK_KEY_Left:
550 case GDK_KEY_4:
551 key_unit_move(DIR8_WEST);
552 return TRUE;
553
554 case GDK_KEY_KP_Home:
555 case GDK_KEY_KP_7:
556 case GDK_KEY_Home:
557 case GDK_KEY_7:
558 key_unit_move(DIR8_NORTHWEST);
559 return TRUE;
560
561 case GDK_KEY_KP_Begin:
562 case GDK_KEY_KP_5:
563 case GDK_KEY_5:
564 key_recall_previous_focus_unit();
565 return TRUE;
566
567 case GDK_KEY_Escape:
568 key_cancel_action();
569 return TRUE;
570
571 case GDK_KEY_b:
572 if (tiles_hilited_cities) {
573 buy_production_in_selected_cities();
574 return TRUE;
575 }
576 break;
577
578 default:
579 break;
580 };
581
582 return FALSE;
583}
584
585/**********************************************************************/
588 static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev,
589 gpointer data)
590{
591 /* inputline history code */
592 if (!gtk_widget_get_mapped(top_vbox) || inputline_has_focus()) {
593 return FALSE;
594 }
595
596 if (editor_is_active()) {
597 return handle_edit_key_release(ev);
598 }
599
600 return FALSE;
601}
602
603/**********************************************************************/
606 static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev,
607 gpointer data)
608{
609 if (inputline_has_focus()) {
610 return FALSE;
611 }
612
613 if (ev->keyval == GDK_KEY_apostrophe) {
614 /* Allow this even if not in main map view; chatline is present on
615 * some other pages too */
616
617 /* Make the chatline visible if it's not currently.
618 * FIXME: should find the correct window, even when detached, from any
619 * other window; should scroll to the bottom automatically showing the
620 * latest text from other players; MUST NOT make spurious text windows
621 * at the bottom of other dialogs. */
622 if (gtk_widget_get_mapped(top_vbox)) {
623 /* The main game view is visible. May need to switch notebook. */
624 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
625 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 1);
626 } else {
627 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
628 }
629 }
630
631 /* If the chatline is (now) visible, focus it. */
632 if (inputline_is_visible()) {
633 inputline_grab_focus();
634 return TRUE;
635 }
636 }
637
638 if (!gtk_widget_get_mapped(top_vbox)
639 || !can_client_change_view()) {
640 return FALSE;
641 }
642
643 if (editor_is_active()) {
644 if (handle_edit_key_press(ev)) {
645 return TRUE;
646 }
647 }
648
649 if (ev->state & GDK_SHIFT_MASK) {
650 switch (ev->keyval) {
651
652 case GDK_KEY_Return:
653 case GDK_KEY_KP_Enter:
654 key_end_turn();
655 return TRUE;
656
657 default:
658 break;
659 }
660 }
661
662 if (0 == gtk_notebook_get_current_page(GTK_NOTEBOOK(top_notebook))) {
663 /* 0 means the map view is focused. */
664 return key_press_map_canvas(w, ev, data);
665 }
666
667#if 0
668 /* We are focused some other dialog, tab, or widget. */
669 if ((ev->state & GDK_CONTROL_MASK)) {
670 } else if ((ev->state & GDK_SHIFT_MASK)) {
671 } else {
672 switch (ev->keyval) {
673
674 case GDK_KEY_F4:
675 map_canvas_focus();
676 return TRUE;
677
678 default:
679 break;
680 };
681 }
682#endif /* 0 */
683
684 return FALSE;
685}
686
687/**********************************************************************/
690 static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
691{
692 int scroll_x, scroll_y, xstep, ystep;
693
694 if (!can_client_change_view()) {
695 return FALSE;
696 }
697
698 get_mapview_scroll_pos(&scroll_x, &scroll_y);
699 get_mapview_scroll_step(&xstep, &ystep);
700
701 switch (ev->direction) {
702 case GDK_SCROLL_UP:
703 scroll_y -= ystep*2;
704 break;
705 case GDK_SCROLL_DOWN:
706 scroll_y += ystep*2;
707 break;
708 case GDK_SCROLL_RIGHT:
709 scroll_x += xstep*2;
710 break;
711 case GDK_SCROLL_LEFT:
712 scroll_x -= xstep*2;
713 break;
714 default:
715 return FALSE;
716 };
717
718 set_mapview_scroll_pos(scroll_x, scroll_y, mouse_zoom);
719
720 /* Emulating mouse move now */
721 if (!gtk_widget_has_focus(map_canvas)) {
722 gtk_widget_grab_focus(map_canvas);
723 }
724
725 update_line(ev->x, ev->y);
726 if (rbutton_down && (ev->state & GDK_BUTTON3_MASK)) {
727 update_selection_rectangle(ev->x, ev->y);
728 }
729
730 if (keyboardless_goto_button_down && hover_state == HOVER_NONE) {
731 maybe_activate_keyboardless_goto(cur_x, cur_y);
732 }
733
734 control_mouse_cursor(canvas_pos_to_tile(cur_x, cur_y, mouse_zoom));
735
736 return TRUE;
737}
738
739/**********************************************************************/
742 static void tearoff_destroy(GtkWidget *w, gpointer data)
743{
744 GtkWidget *p, *b, *box;
745
746 box = GTK_WIDGET(data);
747 p = g_object_get_data(G_OBJECT(w), "parent");
748 b = g_object_get_data(G_OBJECT(w), "toggle");
749 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), FALSE);
750
751 gtk_widget_hide(w);
752 gtk_widget_reparent(box, p);
753}
754
755/**********************************************************************/
758 static gboolean propagate_keypress(GtkWidget *w, GdkEvent *ev)
759{
760 gtk_widget_event(toplevel, ev);
761
762 return FALSE;
763}
764
765/**********************************************************************/
769 static void tearoff_callback(GtkWidget *b, gpointer data)
770{
771 GtkWidget *box = GTK_WIDGET(data);
772 GtkWidget *w;
773
774 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
775 GtkWidget *temp_hide;
776
777 w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
778 setup_dialog(w, toplevel);
779 gtk_widget_set_name(w, "Freeciv");
780 gtk_window_set_title(GTK_WINDOW(w), _("Freeciv"));
781 gtk_window_set_position(GTK_WINDOW(w), GTK_WIN_POS_MOUSE);
782 g_signal_connect(w, "destroy", G_CALLBACK(tearoff_destroy), box);
783 g_signal_connect(w, "key_press_event",
784 G_CALLBACK(propagate_keypress), NULL);
785
786 g_object_set_data(G_OBJECT(w), "parent", gtk_widget_get_parent(box));
787 g_object_set_data(G_OBJECT(w), "toggle", b);
788 temp_hide = g_object_get_data(G_OBJECT(box), "hide-over-reparent");
789 if (temp_hide != NULL) {
790 gtk_widget_hide(temp_hide);
791 }
792 gtk_widget_reparent(box, w);
793 gtk_widget_show(w);
794 if (temp_hide != NULL) {
795 gtk_widget_show(temp_hide);
796 }
797 } else {
798 gtk_widget_destroy(gtk_widget_get_parent(box));
799 }
800}
801
802/**********************************************************************/
805 static GtkWidget *detached_widget_new(void)
806{
807 GtkWidget *hgrid = gtk_grid_new();
808
809 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 2);
810 return hgrid;
811}
812
813/**********************************************************************/
817 static GtkWidget *detached_widget_fill(GtkWidget *tearbox)
818{
819 GtkWidget *b, *fillbox;
820
821 b = gtk_toggle_button_new();
822 gtk_container_add(GTK_CONTAINER(tearbox), b);
823 g_signal_connect(b, "toggled", G_CALLBACK(tearoff_callback), tearbox);
824 gtk_widget_set_tooltip_text(b, _("Detach/Attach the pane."));
825
826 fillbox = gtk_grid_new();
827 gtk_orientable_set_orientation(GTK_ORIENTABLE(fillbox),
828 GTK_ORIENTATION_VERTICAL);
829
830 gtk_container_add(GTK_CONTAINER(tearbox), fillbox);
831
832 return fillbox;
833}
834
835/**********************************************************************/
842 static void populate_unit_image_table(void)
843{
844 int i, width;
845 GtkWidget *table = unit_image_table;
846 GdkPixbuf *pix;
847 int ttw;
848
849 /* Get width of the overview window */
850 width = (overview_canvas_store_width > GUI_GTK_OVERVIEW_MIN_XSIZE)
851 ? overview_canvas_store_width
852 : GUI_GTK_OVERVIEW_MIN_XSIZE;
853
854 ttw = tileset_tile_width(tileset);
855
856 if (GUI_GTK_OPTION(small_display_layout)) {
857 /* We want arrow to appear if there is other units in addition
858 to active one in tile. Active unit is not counted, so there
859 can be 0 other units to not to display arrow. */
860 num_units_below = 1 - 1;
861 } else {
862 num_units_below = width / ttw;
863 num_units_below = CLIP(1, num_units_below, MAX_NUM_UNITS_BELOW);
864 }
865
866 /* Top row: the active unit. */
867 /* Note, we ref this and other widgets here so that we can unref them
868 * in reset_unit_table. */
869 unit_image = gtk_image_new();
870 gtk_widget_add_events(unit_image, GDK_BUTTON_PRESS_MASK);
871 g_object_ref(unit_image);
872 unit_image_button = gtk_event_box_new();
873 gtk_widget_set_size_request(unit_image_button, ttw, -1);
874 gtk_event_box_set_visible_window(GTK_EVENT_BOX(unit_image_button), FALSE);
875 g_object_ref(unit_image_button);
876 gtk_container_add(GTK_CONTAINER(unit_image_button), unit_image);
877 gtk_grid_attach(GTK_GRID(table), unit_image_button, 0, 0, 1, 1);
878 g_signal_connect(unit_image_button, "button_press_event",
879 G_CALLBACK(select_unit_image_callback),
880 GINT_TO_POINTER(-1));
881
882 if (!GUI_GTK_OPTION(small_display_layout)) {
883 /* Bottom row: other units in the same tile. */
884 for (i = 0; i < num_units_below; i++) {
885 unit_below_image[i] = gtk_image_new();
886 g_object_ref(unit_below_image[i]);
887 gtk_widget_add_events(unit_below_image[i], GDK_BUTTON_PRESS_MASK);
888 unit_below_image_button[i] = gtk_event_box_new();
889 g_object_ref(unit_below_image_button[i]);
890 gtk_widget_set_size_request(unit_below_image_button[i], ttw, -1);
891 gtk_event_box_set_visible_window(GTK_EVENT_BOX(unit_below_image_button[i]),
892 FALSE);
893 gtk_container_add(GTK_CONTAINER(unit_below_image_button[i]),
894 unit_below_image[i]);
895 g_signal_connect(unit_below_image_button[i],
896 "button_press_event",
897 G_CALLBACK(select_unit_image_callback),
898 GINT_TO_POINTER(i));
899
900 gtk_grid_attach(GTK_GRID(table), unit_below_image_button[i],
901 i, 1, 1, 1);
902 }
903 }
904
905 /* Create arrow (popup for all units on the selected tile) */
906 pix = sprite_get_pixbuf(get_arrow_sprite(tileset, ARROW_RIGHT));
907 more_arrow_pixmap = gtk_image_new_from_pixbuf(pix);
908 g_object_ref(more_arrow_pixmap);
909 more_arrow_pixmap_button = gtk_event_box_new();
910 g_object_ref(more_arrow_pixmap_button);
911 gtk_event_box_set_visible_window(GTK_EVENT_BOX(more_arrow_pixmap_button),
912 FALSE);
913 gtk_container_add(GTK_CONTAINER(more_arrow_pixmap_button),
914 more_arrow_pixmap);
915 g_signal_connect(more_arrow_pixmap_button,
916 "button_press_event",
917 G_CALLBACK(select_more_arrow_pixmap_callback), NULL);
918 /* An extra layer so that we can hide the clickable button but keep
919 * an explicit size request to avoid the layout jumping around */
920 more_arrow_pixmap_container = gtk_alignment_new(0.5, 0.5, 0, 0);
921 g_object_ref(more_arrow_pixmap_container);
922 gtk_container_add(GTK_CONTAINER(more_arrow_pixmap_container),
923 more_arrow_pixmap_button);
924 gtk_widget_set_size_request(more_arrow_pixmap_container,
925 gdk_pixbuf_get_width(pix), -1);
926 g_object_unref(G_OBJECT(pix));
927
928 if (!GUI_GTK_OPTION(small_display_layout)) {
929 /* Display on bottom row. */
930 gtk_grid_attach(GTK_GRID(table), more_arrow_pixmap_container,
931 num_units_below, 1, 1, 1);
932 } else {
933 /* Display on top row (there is no bottom row). */
934 gtk_grid_attach(GTK_GRID(table), more_arrow_pixmap_container,
935 1, 0, 1, 1);
936 }
937
938 gtk_widget_show_all(table);
939}
940
941/**********************************************************************/
944 static void free_unit_table(void)
945{
946 if (unit_image_button) {
947 gtk_container_remove(GTK_CONTAINER(unit_image_table),
948 unit_image_button);
949 g_object_unref(unit_image);
950 g_object_unref(unit_image_button);
951 if (!GUI_GTK_OPTION(small_display_layout)) {
952 int i;
953
954 for (i = 0; i < num_units_below; i++) {
955 gtk_container_remove(GTK_CONTAINER(unit_image_table),
956 unit_below_image_button[i]);
957 g_object_unref(unit_below_image[i]);
958 g_object_unref(unit_below_image_button[i]);
959 }
960 }
961 gtk_container_remove(GTK_CONTAINER(unit_image_table),
962 more_arrow_pixmap_container);
963 g_object_unref(more_arrow_pixmap);
964 g_object_unref(more_arrow_pixmap_button);
965 g_object_unref(more_arrow_pixmap_container);
966 }
967}
968
969/**********************************************************************/
972 void reset_unit_table(void)
973{
974 /* Unreference all of the widgets that we're about to reallocate, thus
975 * avoiding a memory leak. Remove them from the container first, just
976 * to be safe. Note, the widgets are ref'd in
977 * populate_unit_image_table. */
978 free_unit_table();
979
980 populate_unit_image_table();
981
982 /* We have to force a redraw of the units. And we explicitly have
983 * to force a redraw of the focus unit, which is normally only
984 * redrawn when the focus changes. We also have to force the 'more'
985 * arrow to go away, both by expicitly hiding it and telling it to
986 * do so (this will be reset immediately afterwards if necessary,
987 * but we have to make the *internal* state consistent). */
988 gtk_widget_hide(more_arrow_pixmap_button);
989 set_unit_icons_more_arrow(FALSE);
990 if (get_num_units_in_focus() == 1) {
991 set_unit_icon(-1, head_of_units_in_focus());
992 } else {
993 set_unit_icon(-1, NULL);
994 }
995 update_unit_pix_label(get_units_in_focus());
996}
997
998/**********************************************************************/
1001 void enable_menus(bool enable)
1002{
1003 if (enable) {
1004 main_menubar = setup_menus(toplevel);
1005 /* Ensure the menus are really created before performing any operations
1006 * on them. */
1007 while (gtk_events_pending()) {
1008 gtk_main_iteration();
1009 }
1010 gtk_grid_attach_next_to(GTK_GRID(top_vbox), main_menubar, NULL, GTK_POS_TOP, 1, 1);
1011 menus_init();
1012 gtk_widget_show_all(main_menubar);
1013 } else {
1014 gtk_widget_destroy(main_menubar);
1015 }
1016}
1017
1018/**********************************************************************/
1024 static gboolean right_notebook_button_release(GtkWidget *widget,
1025 GdkEventButton *event)
1026{
1027 if (event->type != GDK_BUTTON_RELEASE) {
1028 return FALSE;
1029 }
1030
1031 if (!GTK_IS_NOTEBOOK(widget)
1032 || -1 == gtk_notebook_get_current_page(GTK_NOTEBOOK(widget))) {
1033 /* Make sure the default gtk handler
1034 * does NOT get called in this case. */
1035 return TRUE;
1036 }
1037
1038 return FALSE;
1039}
1040
1041/**********************************************************************/
1044 static void setup_canvas_color_for_state(GtkStateFlags state)
1045{
1046 gtk_widget_override_background_color(GTK_WIDGET(overview_canvas), state,
1047 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1048 gtk_widget_override_background_color(GTK_WIDGET(map_canvas), state,
1049 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1050}
1051
1052/**********************************************************************/
1055 void update_turn_done_tooltip(void)
1056{
1057 struct option *opt = optset_option_by_name(server_optset, "fixedlength");
1058
1059 if (opt != NULL && option_bool_get(opt)) {
1060 gtk_widget_set_tooltip_text(turn_done_button,
1061 _("Fixed length turns"));
1062 } else {
1063 char buf[256];
1064
1065 fc_snprintf(buf, sizeof(buf), "%s:\n%s",
1066 _("Turn Done"), _("Shift+Return"));
1067 gtk_widget_set_tooltip_text(turn_done_button, buf);
1068 }
1069}
1070
1071/**********************************************************************/
1074 static void setup_widgets(void)
1075{
1076 GtkWidget *page, *ebox, *hgrid, *hgrid2, *label;
1077 GtkWidget *frame, *table, *table2, *paned, *sw, *text;
1078 GtkWidget *button, *view, *vgrid, *right_vbox = NULL;
1079 int i;
1080 struct sprite *spr;
1081 GtkWidget *notebook, *statusbar;
1082 GtkWidget *dtach_lowbox = NULL;
1083
1084 message_buffer = gtk_text_buffer_new(NULL);
1085
1086 notebook = gtk_notebook_new();
1087
1088 /* Stop mouse wheel notebook page switching. */
1089 g_signal_connect(notebook, "scroll_event",
1090 G_CALLBACK(gtk_true), NULL);
1091
1092 toplevel_tabs = notebook;
1093 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1094 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1095 vgrid = gtk_grid_new();
1096 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1097 GTK_ORIENTATION_VERTICAL);
1098 gtk_grid_set_row_spacing(GTK_GRID(vgrid), 4);
1099 gtk_container_add(GTK_CONTAINER(toplevel), vgrid);
1100 gtk_container_add(GTK_CONTAINER(vgrid), notebook);
1101 statusbar = create_statusbar();
1102 gtk_container_add(GTK_CONTAINER(vgrid), statusbar);
1103
1104 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1105 create_main_page(), NULL);
1106 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1107 create_start_page(), NULL);
1108 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1109 create_scenario_page(), NULL);
1110 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1111 create_load_page(), NULL);
1112 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1113 create_network_page(), NULL);
1114
1115 editgui_create_widgets();
1116
1117 ingame_votebar = voteinfo_bar_new(FALSE);
1118 g_object_set(ingame_votebar, "margin", 2, NULL);
1119
1120 /* *** everything in the top *** */
1121
1122 page = gtk_scrolled_window_new(NULL, NULL);
1123 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page),
1124 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1125 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(page),
1126 GTK_SHADOW_ETCHED_IN);
1127 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, NULL);
1128
1129 top_vbox = gtk_grid_new();
1130 gtk_orientable_set_orientation(GTK_ORIENTABLE(top_vbox),
1131 GTK_ORIENTATION_VERTICAL);
1132 gtk_grid_set_row_spacing(GTK_GRID(top_vbox), 5);
1133 hgrid = gtk_grid_new();
1134
1135 if (GUI_GTK_OPTION(small_display_layout)) {
1136 /* The window is divided into two horizontal panels: overview +
1137 * civinfo + unitinfo, main view + message window. */
1138 right_vbox = gtk_grid_new();
1139 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1140 GTK_ORIENTATION_VERTICAL);
1141 gtk_container_add(GTK_CONTAINER(hgrid), right_vbox);
1142
1143 paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1144 gtk_container_add(GTK_CONTAINER(page), top_vbox);
1145 gtk_container_add(GTK_CONTAINER(top_vbox), hgrid);
1146 gtk_container_add(GTK_CONTAINER(right_vbox), paned);
1147 gtk_container_add(GTK_CONTAINER(right_vbox), ingame_votebar);
1148
1149 /* Overview size designed for small displays (netbooks). */
1150 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK;
1151 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK;
1152 } else {
1153 /* The window is divided into two vertical panes: overview +
1154 * + civinfo + unitinfo + main view, message window. */
1155 paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1156 gtk_container_add(GTK_CONTAINER(page), paned);
1157 gtk_paned_pack1(GTK_PANED(paned), top_vbox, TRUE, FALSE);
1158 gtk_container_add(GTK_CONTAINER(top_vbox), hgrid);
1159
1160 /* Overview size designed for big displays (desktops). */
1161 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
1162 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
1163 }
1164
1165 /* This holds the overview canvas, production info, etc. */
1166 vgrid = gtk_grid_new();
1167 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1168 GTK_ORIENTATION_VERTICAL);
1169 gtk_grid_set_column_spacing(GTK_GRID(vgrid), 3);
1170 /* Put vgrid to the left of anything else in hgrid -- right_vbox is either
1171 * the chat/messages pane, or NULL which is OK */
1172 gtk_grid_attach_next_to(GTK_GRID(hgrid), vgrid, right_vbox,
1173 GTK_POS_LEFT, 1, 1);
1174
1175 /* Overview canvas */
1176 ahbox = detached_widget_new();
1177 gtk_widget_set_hexpand(ahbox, FALSE);
1178 gtk_widget_set_vexpand(ahbox, FALSE);
1179 gtk_container_add(GTK_CONTAINER(vgrid), ahbox);
1180 avbox = detached_widget_fill(ahbox);
1181
1182 overview_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1183 gtk_container_set_border_width(GTK_CONTAINER (overview_scrolled_window), 1);
1184 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (overview_scrolled_window),
1185 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1186
1187 overview_canvas = gtk_drawing_area_new();
1188 gtk_widget_set_halign(overview_canvas, GTK_ALIGN_CENTER);
1189 gtk_widget_set_valign(overview_canvas, GTK_ALIGN_CENTER);
1190 gtk_widget_set_size_request(overview_canvas, overview_canvas_store_width,
1191 overview_canvas_store_height);
1192 gtk_widget_set_size_request(overview_scrolled_window, overview_canvas_store_width,
1193 overview_canvas_store_height);
1194 gtk_widget_set_hexpand(overview_canvas, TRUE);
1195 gtk_widget_set_vexpand(overview_canvas, TRUE);
1196
1197 gtk_widget_add_events(overview_canvas, GDK_EXPOSURE_MASK
1198 |GDK_BUTTON_PRESS_MASK
1199 |GDK_POINTER_MOTION_MASK);
1200 gtk_container_add(GTK_CONTAINER(avbox), overview_scrolled_window);
1201
1202 gtk_container_add(GTK_CONTAINER(overview_scrolled_window),
1203 overview_canvas);
1204
1205 g_signal_connect(overview_canvas, "draw",
1206 G_CALLBACK(overview_canvas_draw), NULL);
1207
1208 g_signal_connect(overview_canvas, "motion_notify_event",
1209 G_CALLBACK(move_overviewcanvas), NULL);
1210
1211 g_signal_connect(overview_canvas, "button_press_event",
1212 G_CALLBACK(butt_down_overviewcanvas), NULL);
1213
1214 /* The rest */
1215
1216 ahbox = detached_widget_new();
1217 gtk_container_add(GTK_CONTAINER(vgrid), ahbox);
1218 gtk_widget_set_hexpand(ahbox, FALSE);
1219 avbox = detached_widget_fill(ahbox);
1220 gtk_widget_set_vexpand(avbox, TRUE);
1221 gtk_widget_set_valign(avbox, GTK_ALIGN_FILL);
1222
1223 /* Info on player's civilization, when game is running. */
1224 frame = gtk_frame_new("");
1225 gtk_container_add(GTK_CONTAINER(avbox), frame);
1226
1227 main_frame_civ_name = frame;
1228
1229 vgrid = gtk_grid_new();
1230 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1231 GTK_ORIENTATION_VERTICAL);
1232 gtk_container_add(GTK_CONTAINER(frame), vgrid);
1233 gtk_widget_set_hexpand(vgrid, TRUE);
1234
1235 ebox = gtk_event_box_new();
1236 gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK);
1237 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1238 g_signal_connect(ebox, "button_press_event",
1239 G_CALLBACK(show_info_popup), NULL);
1240 gtk_container_add(GTK_CONTAINER(vgrid), ebox);
1241
1242 label = gtk_label_new(NULL);
1243 gtk_widget_set_halign(label, GTK_ALIGN_START);
1244 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1245 gtk_widget_set_margin_left(label, 2);
1246 gtk_widget_set_margin_right(label, 2);
1247 gtk_widget_set_margin_top(label, 2);
1248 gtk_widget_set_margin_bottom(label, 2);
1249 gtk_container_add(GTK_CONTAINER(ebox), label);
1250 main_label_info = label;
1251
1252 /* Production status */
1253 table = gtk_grid_new();
1254 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
1255 gtk_grid_set_column_homogeneous(GTK_GRID(table), TRUE);
1256 gtk_container_add(GTK_CONTAINER(avbox), table);
1257
1258 /* Citizens for taxrates */
1259 ebox = gtk_event_box_new();
1260 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1261 gtk_grid_attach(GTK_GRID(table), ebox, 0, 0, 10, 1);
1262 econ_ebox = ebox;
1263
1264 table2 = gtk_grid_new();
1265 gtk_container_add(GTK_CONTAINER(ebox), table2);
1266
1267 for (i = 0; i < 10; i++) {
1268 ebox = gtk_event_box_new();
1269 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1270 gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK);
1271
1272 gtk_grid_attach(GTK_GRID(table2), ebox, i, 0, 1, 1);
1273
1274 g_signal_connect(ebox, "button_press_event",
1275 G_CALLBACK(taxrates_callback), GINT_TO_POINTER(i));
1276
1277 spr = i < 5 ? get_tax_sprite(tileset, O_SCIENCE) : get_tax_sprite(tileset, O_GOLD);
1278 econ_label[i] = gtk_image_new_from_surface(spr->surface);
1279 gtk_container_add(GTK_CONTAINER(ebox), econ_label[i]);
1280 }
1281
1282 /* Science, environmental, govt, timeout */
1283 spr = client_research_sprite();
1284 if (spr != NULL) {
1285 bulb_label = gtk_image_new_from_surface(spr->surface);
1286 }
1287 spr = client_warming_sprite();
1288 if (spr != NULL) {
1289 sun_label = gtk_image_new_from_surface(spr->surface);
1290 }
1291 spr = client_cooling_sprite();
1292 if (spr != NULL) {
1293 flake_label = gtk_image_new_from_surface(spr->surface);
1294 }
1295 spr = client_government_sprite();
1296 if (spr != NULL) {
1297 government_label = gtk_image_new_from_surface(spr->surface);
1298 }
1299
1300 for (i = 0; i < 4; i++) {
1301 GtkWidget *w;
1302
1303 ebox = gtk_event_box_new();
1304 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1305
1306 switch (i) {
1307 case 0:
1308 w = bulb_label;
1309 bulb_ebox = ebox;
1310 break;
1311 case 1:
1312 w = sun_label;
1313 sun_ebox = ebox;
1314 break;
1315 case 2:
1316 w = flake_label;
1317 flake_ebox = ebox;
1318 break;
1319 default:
1320 case 3:
1321 w = government_label;
1322 government_ebox = ebox;
1323 break;
1324 }
1325
1326 gtk_widget_set_halign(w, GTK_ALIGN_START);
1327 gtk_widget_set_valign(w, GTK_ALIGN_START);
1328 gtk_widget_set_margin_left(w, 0);
1329 gtk_widget_set_margin_right(w, 0);
1330 gtk_widget_set_margin_top(w, 0);
1331 gtk_widget_set_margin_bottom(w, 0);
1332 gtk_container_add(GTK_CONTAINER(ebox), w);
1333 gtk_grid_attach(GTK_GRID(table), ebox, i, 1, 1, 1);
1334 }
1335
1336 timeout_label = gtk_label_new("");
1337
1338 frame = gtk_frame_new(NULL);
1339 gtk_grid_attach(GTK_GRID(table), frame, 4, 1, 6, 1);
1340 gtk_container_add(GTK_CONTAINER(frame), timeout_label);
1341
1342
1343 /* Turn done */
1344 turn_done_button = gtk_button_new_with_label(_("Turn Done"));
1345
1346 gtk_grid_attach(GTK_GRID(table), turn_done_button, 0, 2, 10, 1);
1347
1348 g_signal_connect(turn_done_button, "clicked",
1349 G_CALLBACK(end_turn_callback), NULL);
1350
1351 update_turn_done_tooltip();
1352
1353 /* Selected unit status */
1354
1355 unit_info_box = gtk_grid_new();
1356 gtk_widget_set_hexpand(unit_info_box, FALSE);
1357 gtk_orientable_set_orientation(GTK_ORIENTABLE(unit_info_box),
1358 GTK_ORIENTATION_VERTICAL);
1359 gtk_container_add(GTK_CONTAINER(avbox), unit_info_box);
1360
1361 /* In edit mode the unit_info_box widget is replaced by the
1362 * editinfobox, so we need to add a ref here so that it is
1363 * not destroyed when removed from its container.
1364 * See editinfobox_refresh(). */
1365 g_object_ref(unit_info_box);
1366
1367 unit_info_frame = gtk_frame_new("");
1368 gtk_container_add(GTK_CONTAINER(unit_info_box), unit_info_frame);
1369
1370 sw = gtk_scrolled_window_new(NULL, NULL);
1371 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1372 GTK_SHADOW_OUT);
1373 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1374 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1375 gtk_container_add(GTK_CONTAINER(unit_info_frame), sw);
1376
1377 label = gtk_label_new(NULL);
1378 gtk_widget_set_hexpand(label, TRUE);
1379 gtk_widget_set_halign(label, GTK_ALIGN_START);
1380 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1381 gtk_widget_set_margin_left(label, 2);
1382 gtk_widget_set_margin_right(label, 2);
1383 gtk_widget_set_margin_top(label, 2);
1384 gtk_widget_set_margin_bottom(label, 2);
1385 gtk_container_add(GTK_CONTAINER(sw), label);
1386 unit_info_label = label;
1387
1388 hgrid2 = gtk_grid_new();
1389 gtk_container_add(GTK_CONTAINER(unit_info_box), hgrid2);
1390
1391 table = gtk_grid_new();
1392 g_object_set(table, "margin", 5, NULL);
1393 gtk_container_add(GTK_CONTAINER(hgrid2), table);
1394
1395 gtk_grid_set_row_spacing(GTK_GRID(table), 2);
1396 gtk_grid_set_column_spacing(GTK_GRID(table), 2);
1397
1398 unit_image_table = table;
1399
1400 /* Map canvas, editor toolbar, and scrollbars */
1401
1402 /* The top notebook containing the map view and dialogs. */
1403
1404 top_notebook = gtk_notebook_new();
1405 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(top_notebook), GTK_POS_BOTTOM);
1406 gtk_notebook_set_scrollable(GTK_NOTEBOOK(top_notebook), TRUE);
1407
1408
1409 if (GUI_GTK_OPTION(small_display_layout)) {
1410 gtk_paned_pack1(GTK_PANED(paned), top_notebook, TRUE, FALSE);
1411 } else if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1412 right_vbox = gtk_grid_new();
1413 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1414 GTK_ORIENTATION_VERTICAL);
1415
1416 gtk_container_add(GTK_CONTAINER(right_vbox), top_notebook);
1417 gtk_container_add(GTK_CONTAINER(right_vbox), ingame_votebar);
1418 gtk_container_add(GTK_CONTAINER(hgrid), right_vbox);
1419 } else {
1420 gtk_container_add(GTK_CONTAINER(hgrid), top_notebook);
1421 }
1422
1423 map_widget = gtk_grid_new();
1424
1425 vgrid = gtk_grid_new();
1426 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1427 GTK_ORIENTATION_VERTICAL);
1428 gtk_container_add(GTK_CONTAINER(vgrid), map_widget);
1429
1430 gtk_container_add(GTK_CONTAINER(vgrid), editgui_get_editbar()->widget);
1431 g_object_set(editgui_get_editbar()->widget, "margin", 4, NULL);
1432
1433 label = gtk_label_new(Q_("?noun:View"));
1434 gtk_notebook_append_page(GTK_NOTEBOOK(top_notebook), vgrid, label);
1435
1436 frame = gtk_frame_new(NULL);
1437 gtk_grid_attach(GTK_GRID(map_widget), frame, 0, 0, 1, 1);
1438
1439 map_canvas = gtk_drawing_area_new();
1440 gtk_widget_set_hexpand(map_canvas, TRUE);
1441 gtk_widget_set_vexpand(map_canvas, TRUE);
1442 gtk_widget_set_size_request(map_canvas, 300, 300);
1443 gtk_widget_set_can_focus(map_canvas, TRUE);
1444
1445 setup_canvas_color_for_state(GTK_STATE_FLAG_NORMAL);
1446 setup_canvas_color_for_state(GTK_STATE_FLAG_ACTIVE);
1447 setup_canvas_color_for_state(GTK_STATE_FLAG_PRELIGHT);
1448 setup_canvas_color_for_state(GTK_STATE_FLAG_SELECTED);
1449 setup_canvas_color_for_state(GTK_STATE_FLAG_INSENSITIVE);
1450 setup_canvas_color_for_state(GTK_STATE_FLAG_INCONSISTENT);
1451 setup_canvas_color_for_state(GTK_STATE_FLAG_FOCUSED);
1452 setup_canvas_color_for_state(GTK_STATE_FLAG_BACKDROP);
1453
1454 gtk_widget_add_events(map_canvas, GDK_EXPOSURE_MASK
1455 |GDK_BUTTON_PRESS_MASK
1456 |GDK_BUTTON_RELEASE_MASK
1457 |GDK_KEY_PRESS_MASK
1458 |GDK_POINTER_MOTION_MASK
1459 |GDK_SCROLL_MASK);
1460
1461 gtk_container_add(GTK_CONTAINER(frame), map_canvas);
1462
1463 map_horizontal_scrollbar =
1464 gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
1465 gtk_grid_attach(GTK_GRID(map_widget), map_horizontal_scrollbar, 0, 1, 1, 1);
1466
1467 map_vertical_scrollbar =
1468 gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
1469 gtk_grid_attach(GTK_GRID(map_widget), map_vertical_scrollbar, 1, 0, 1, 1);
1470
1471 g_signal_connect(map_canvas, "draw",
1472 G_CALLBACK(map_canvas_draw), NULL);
1473
1474 g_signal_connect(map_canvas, "configure_event",
1475 G_CALLBACK(map_canvas_configure), NULL);
1476
1477 g_signal_connect(map_canvas, "motion_notify_event",
1478 G_CALLBACK(move_mapcanvas), NULL);
1479
1480 g_signal_connect(toplevel, "enter_notify_event",
1481 G_CALLBACK(leave_mapcanvas), NULL);
1482
1483 g_signal_connect(map_canvas, "button_press_event",
1484 G_CALLBACK(butt_down_mapcanvas), NULL);
1485
1486 g_signal_connect(map_canvas, "button_release_event",
1487 G_CALLBACK(butt_release_mapcanvas), NULL);
1488
1489 g_signal_connect(map_canvas, "scroll_event",
1490 G_CALLBACK(mouse_scroll_mapcanvas), NULL);
1491
1492 g_signal_connect(toplevel, "key_press_event",
1493 G_CALLBACK(toplevel_key_press_handler), NULL);
1494
1495 g_signal_connect(toplevel, "key_release_event",
1496 G_CALLBACK(toplevel_key_release_handler), NULL);
1497
1498 /* *** The message window -- this is a detachable widget *** */
1499
1500 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1501 bottom_hpaned = paned;
1502 right_notebook = bottom_notebook = top_notebook;
1503 } else {
1504 GtkWidget *hpaned;
1505
1506 dtach_lowbox = detached_widget_new();
1507 gtk_paned_pack2(GTK_PANED(paned), dtach_lowbox, FALSE, TRUE);
1508 avbox = detached_widget_fill(dtach_lowbox);
1509
1510 vgrid = gtk_grid_new();
1511 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1512 GTK_ORIENTATION_VERTICAL);
1513 if (!GUI_GTK_OPTION(small_display_layout)) {
1514 gtk_container_add(GTK_CONTAINER(vgrid), ingame_votebar);
1515 }
1516 gtk_container_add(GTK_CONTAINER(avbox), vgrid);
1517
1518 if (GUI_GTK_OPTION(small_display_layout)) {
1519 hpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1520 } else {
1521 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1522 }
1523 gtk_container_add(GTK_CONTAINER(vgrid), hpaned);
1524 g_object_set(hpaned, "margin", 4, NULL);
1525 bottom_hpaned = hpaned;
1526
1527 bottom_notebook = gtk_notebook_new();
1528 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(bottom_notebook), GTK_POS_TOP);
1529 gtk_notebook_set_scrollable(GTK_NOTEBOOK(bottom_notebook), TRUE);
1530 gtk_paned_pack1(GTK_PANED(hpaned), bottom_notebook, TRUE, TRUE);
1531
1532 right_notebook = gtk_notebook_new();
1533 g_object_ref(right_notebook);
1534 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(right_notebook), GTK_POS_TOP);
1535 gtk_notebook_set_scrollable(GTK_NOTEBOOK(right_notebook), TRUE);
1536 g_signal_connect(right_notebook, "button-release-event",
1537 G_CALLBACK(right_notebook_button_release), NULL);
1538 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
1539 gtk_paned_pack2(GTK_PANED(hpaned), right_notebook, TRUE, TRUE);
1540 }
1541 }
1542
1543 vgrid = gtk_grid_new();
1544 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1545 GTK_ORIENTATION_VERTICAL);
1546
1547 sw = gtk_scrolled_window_new(NULL, NULL);
1548 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1549 GTK_SHADOW_ETCHED_IN);
1550 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC,
1551 GTK_POLICY_ALWAYS);
1552 gtk_container_add(GTK_CONTAINER(vgrid), sw);
1553
1554 label = gtk_label_new(_("Chat"));
1555 gtk_notebook_append_page(GTK_NOTEBOOK(bottom_notebook), vgrid, label);
1556
1557 text = gtk_text_view_new_with_buffer(message_buffer);
1558 gtk_widget_set_hexpand(text, TRUE);
1559 gtk_widget_set_vexpand(text, TRUE);
1560 set_message_buffer_view_link_handlers(text);
1561 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
1562 gtk_container_add(GTK_CONTAINER(sw), text);
1563 g_signal_connect(text, "size-allocate",
1564 G_CALLBACK(main_message_area_size_allocate), NULL);
1565
1566 gtk_widget_set_name(text, "chatline");
1567
1568 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
1569 gtk_widget_realize(text);
1570 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
1571
1572 main_message_area = GTK_TEXT_VIEW(text);
1573 if (dtach_lowbox != NULL) {
1574 g_object_set_data(G_OBJECT(dtach_lowbox), "hide-over-reparent", main_message_area);
1575 }
1576
1577 chat_welcome_message(TRUE);
1578
1579 /* the chat line */
1580 view = inputline_toolkit_view_new();
1581 gtk_container_add(GTK_CONTAINER(vgrid), view);
1582 g_object_set(view, "margin", 3, NULL);
1583
1584 button = gtk_check_button_new_with_label(_("Allies Only"));
1585 gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
1586 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
1587 GUI_GTK_OPTION(allied_chat_only));
1588 g_signal_connect(button, "toggled",
1589 G_CALLBACK(allied_chat_button_toggled), NULL);
1590 inputline_toolkit_view_append_button(view, button);
1591 allied_chat_toggle_button = button;
1592
1593 button = gtk_button_new_with_label(_("Clear links"));
1594 g_signal_connect(button, "clicked",
1595 G_CALLBACK(link_marks_clear_all), NULL);
1596 inputline_toolkit_view_append_button(view, button);
1597
1598 /* Other things to take care of */
1599
1600 gtk_widget_show_all(gtk_bin_get_child(GTK_BIN(toplevel)));
1601
1602 if (GUI_GTK_OPTION(enable_tabs)) {
1603 meswin_dialog_popup(FALSE);
1604 }
1605
1606 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
1607 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
1608
1609 if (!GUI_GTK_OPTION(map_scrollbars)) {
1610 gtk_widget_hide(map_horizontal_scrollbar);
1611 gtk_widget_hide(map_vertical_scrollbar);
1612 }
1613}
1614
1615/**********************************************************************/
1618 void ui_init(void)
1619{
1620 log_set_callback(log_callback_utf8);
1621 set_frame_by_frame_animation();
1622}
1623
1624/**********************************************************************/
1627 int main(int argc, char **argv)
1628{
1629 return client_main(argc, argv, FALSE);
1630}
1631
1632/**********************************************************************/
1635 static void migrate_options_from_gtk2(void)
1636{
1637 log_normal(_("Migrating options from gtk2 to gtk3 client"));
1638
1639#define MIGRATE_OPTION(opt) GUI_GTK_OPTION(opt) = gui_options.gui_gtk2_##opt;
1640#define MIGRATE_STR_OPTION(opt) \
1641 strncpy(GUI_GTK_OPTION(opt), gui_options.gui_gtk2_##opt, \
1642 sizeof(GUI_GTK_OPTION(opt)));
1643
1644 /* Default theme name is never migrated */
1645 /* 'fullscreen', 'small_display_layout', and 'message_chat_location'
1646 * not migrated, as (unlike Gtk2), Gtk3-client tries to pick better
1647 * defaults for these in fresh installations based on screen size (see
1648 * adjust_default_options()); so user is probably better served by
1649 * getting these adaptive defaults than whatever they had for Gtk2.
1650 * Since 'fullscreen' isn't migrated, we don't need to worry about
1651 * preserving gui_gtk2_migrated_from_2_5 either. */
1652 MIGRATE_OPTION(map_scrollbars);
1653 MIGRATE_OPTION(dialogs_on_top);
1654 MIGRATE_OPTION(show_task_icons);
1655 MIGRATE_OPTION(enable_tabs);
1656 MIGRATE_OPTION(show_chat_message_time);
1657 MIGRATE_OPTION(new_messages_go_to_top);
1658 MIGRATE_OPTION(show_message_window_buttons);
1659 MIGRATE_OPTION(metaserver_tab_first);
1660 MIGRATE_OPTION(allied_chat_only);
1661 MIGRATE_OPTION(mouse_over_map_focus);
1662 MIGRATE_OPTION(chatline_autocompletion);
1663 MIGRATE_OPTION(citydlg_xsize);
1664 MIGRATE_OPTION(citydlg_ysize);
1665 MIGRATE_OPTION(popup_tech_help);
1666
1667 MIGRATE_STR_OPTION(font_city_label);
1668 MIGRATE_STR_OPTION(font_notify_label);
1669 MIGRATE_STR_OPTION(font_spaceship_label);
1670 MIGRATE_STR_OPTION(font_help_label);
1671 MIGRATE_STR_OPTION(font_help_link);
1672 MIGRATE_STR_OPTION(font_help_text);
1673 MIGRATE_STR_OPTION(font_chatline);
1674 MIGRATE_STR_OPTION(font_beta_label);
1675 MIGRATE_STR_OPTION(font_small);
1676 MIGRATE_STR_OPTION(font_comment_label);
1677 MIGRATE_STR_OPTION(font_city_names);
1678 MIGRATE_STR_OPTION(font_city_productions);
1679 MIGRATE_STR_OPTION(font_reqtree_text);
1680
1681#undef MIGRATE_OPTION
1682#undef MIGRATE_STR_OPTION
1683
1684 GUI_GTK_OPTION(migrated_from_gtk2) = TRUE;
1685}
1686
1687/**********************************************************************/
1690 static void migrate_options_from_2_5(void)
1691{
1692 log_normal(_("Migrating gtk3-client options from freeciv-2.5 options."));
1693
1694 GUI_GTK_OPTION(fullscreen) = gui_options.migrate_fullscreen;
1695
1696 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1697}
1698
1699/**********************************************************************/
1702 int ui_main(int argc, char **argv)
1703{
1704 PangoFontDescription *toplevel_font_name;
1705 guint sig;
1706
1707 if (parse_options(argc, argv)) {
1708 char window_name[1024];
1709
1710 /* The locale has already been set in init_nls() and the windows-specific
1711 * locale logic in gtk_init() causes problems with zh_CN (see PR#39475) */
1712 gtk_disable_setlocale();
1713
1714 /* GTK withdraw gtk options. Process GTK arguments */
1715 if (!gtk_init_check(&argc, &argv)) {
1716 log_fatal(_("Failed to open graphical mode."));
1717 exit(EXIT_FAILURE);
1718 }
1719
1720 help_system_init();
1721
1722 toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1723 gtk_window_set_position(GTK_WINDOW(toplevel), GTK_WIN_POS_CENTER);
1724 if (vmode.width > 0 && vmode.height > 0) {
1725 gtk_window_resize(GTK_WINDOW(toplevel), vmode.width, vmode.height);
1726 }
1727 g_signal_connect(toplevel, "key_press_event",
1728 G_CALLBACK(toplevel_handler), NULL);
1729
1730 gtk_window_set_role(GTK_WINDOW(toplevel), "toplevel");
1731 gtk_widget_realize(toplevel);
1732 gtk_widget_set_name(toplevel, "Freeciv");
1733 root_window = gtk_widget_get_window(toplevel);
1734
1735 if (gui_options.first_boot) {
1736 adjust_default_options();
1737 /* We're using fresh defaults for this version of this client,
1738 * so prevent any future migrations from other clients / versions */
1739 GUI_GTK_OPTION(migrated_from_gtk2) = TRUE;
1740 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1741 } else {
1742 if (!GUI_GTK_OPTION(migrated_from_gtk2)) {
1743 migrate_options_from_gtk2();
1744 /* We want a fresh look at screen-size-related defaults */
1745 adjust_default_options();
1746 /* We don't ever want to consider pre-2.6 fullscreen option again */
1747 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1748 } else if (!GUI_GTK_OPTION(migrated_from_2_5)) {
1749 /* This only affects the fullscreen option, which we don't want
1750 * to touch if adjust_default_options() just adjusted it. */
1751 migrate_options_from_2_5();
1752 }
1753 }
1754
1755 if (GUI_GTK_OPTION(fullscreen)) {
1756 gtk_window_fullscreen(GTK_WINDOW(toplevel));
1757 }
1758
1759 fc_snprintf(window_name, sizeof(window_name), _("Freeciv (%s)"), GUI_NAME_SHORT);
1760 gtk_window_set_title(GTK_WINDOW(toplevel), window_name);
1761
1762 g_signal_connect(toplevel, "delete_event",
1763 G_CALLBACK(quit_dialog_callback), NULL);
1764
1765 /* Disable GTK+ cursor key focus movement */
1766 sig = g_signal_lookup("focus", GTK_TYPE_WIDGET);
1767 g_signal_handlers_disconnect_matched(toplevel, G_SIGNAL_MATCH_ID, sig,
1768 0, 0, 0, 0);
1769 g_signal_connect(toplevel, "focus", G_CALLBACK(toplevel_focus), NULL);
1770
1771 options_iterate(client_optset, poption) {
1772 if (OT_FONT == option_type(poption)) {
1773 /* Force to call the appropriate callback. */
1774 option_changed(poption);
1775 }
1776 } options_iterate_end;
1777
1778 toplevel_font_name = pango_context_get_font_description(
1779 gtk_widget_get_pango_context(toplevel));
1780
1781 if (NULL == city_names_style) {
1782 city_names_style = pango_font_description_copy(toplevel_font_name);
1783 log_error("city_names_style should have been set by options.");
1784 }
1785 if (NULL == city_productions_style) {
1786 city_productions_style = pango_font_description_copy(toplevel_font_name);
1787 log_error("city_productions_style should have been set by options.");
1788 }
1789 if (NULL == reqtree_text_style) {
1790 reqtree_text_style = pango_font_description_copy(toplevel_font_name);
1791 log_error("reqtree_text_style should have been set by options.");
1792 }
1793
1794 tileset_init(tileset);
1795 tileset_load_tiles(tileset);
1796
1797 /* Keep the icon of the executable on Windows (see PR#36491) */
1798#ifndef FREECIV_MSWINDOWS
1799 {
1800 GdkPixbuf *pixbuf = sprite_get_pixbuf(get_icon_sprite(tileset, ICON_FREECIV));
1801
1802 /* Only call this after tileset_load_tiles is called. */
1803 gtk_window_set_icon(GTK_WINDOW(toplevel), pixbuf);
1804 g_object_unref(pixbuf);
1805 }
1806#endif /* FREECIV_MSWINDOWS */
1807
1808 setup_widgets();
1809 load_cursors();
1810 cma_fe_init();
1811 diplomacy_dialog_init();
1812 luaconsole_dialog_init();
1813 happiness_dialog_init();
1814 citizens_dialog_init();
1815 intel_dialog_init();
1816 spaceship_dialog_init();
1817 chatline_init();
1818 init_mapcanvas_and_overview();
1819
1820 tileset_use_preferred_theme(tileset);
1821
1822 gtk_widget_show(toplevel);
1823
1824 /* Assumes toplevel showing */
1825 set_client_state(C_S_DISCONNECTED);
1826
1827 /* Assumes client_state is set */
1828 timer_id = g_timeout_add(TIMER_INTERVAL, timer_callback, NULL);
1829
1830 gui_up = TRUE;
1831 gtk_main();
1832 gui_up = FALSE;
1833
1834 destroy_server_scans();
1835 free_mapcanvas_and_overview();
1836 spaceship_dialog_done();
1837 intel_dialog_done();
1838 citizens_dialog_done();
1839 luaconsole_dialog_done();
1840 happiness_dialog_done();
1841 diplomacy_dialog_done();
1842 cma_fe_done();
1843 free_unit_table();
1844
1845 /* We have extra ref for unit_info_box that has protected
1846 * it from getting destroyed when editinfobox_refresh()
1847 * moves widgets around. Free that extra ref here. */
1848 g_object_unref(unit_info_box);
1849
1850 editgui_free();
1851 gtk_widget_destroy(toplevel_tabs);
1852 gtk_widget_destroy(toplevel);
1853 menus_free();
1854 message_buffer = NULL; /* Result of destruction of everything */
1855 tileset_free_tiles(tileset);
1856 }
1857
1858 return EXIT_SUCCESS;
1859}
1860
1861/**********************************************************************/
1864 bool is_gui_up(void)
1865{
1866 return gui_up;
1867}
1868
1869/**********************************************************************/
1872 void ui_exit(void)
1873{
1874 if (message_buffer != NULL) {
1875 g_object_unref(message_buffer);
1876 message_buffer = NULL;
1877 }
1878}
1879
1880/**********************************************************************/
1883 enum gui_type get_gui_type(void)
1884{
1885 return GUI_GTK3;
1886}
1887
1888/**********************************************************************/
1891 void sound_bell(void)
1892{
1893 gdk_display_beep(gdk_display_get_default());
1894}
1895
1896/**********************************************************************/
1902 void set_unit_icon(int idx, struct unit *punit)
1903{
1904 GtkWidget *w;
1905
1906 fc_assert_ret(idx >= -1 && idx < num_units_below);
1907
1908 if (idx == -1) {
1909 w = unit_image;
1910 unit_id_top = punit ? punit->id : 0;
1911 } else {
1912 w = unit_below_image[idx];
1913 unit_ids[idx] = punit ? punit->id : 0;
1914 }
1915
1916 if (!w) {
1917 return;
1918 }
1919
1920 if (punit) {
1921 put_unit_image(punit, GTK_IMAGE(w), -1);
1922 } else {
1923 gtk_image_clear(GTK_IMAGE(w));
1924 }
1925}
1926
1927/**********************************************************************/
1932 void set_unit_icons_more_arrow(bool onoff)
1933{
1934 static bool showing = FALSE;
1935
1936 if (!more_arrow_pixmap_button) {
1937 return;
1938 }
1939
1940 if (onoff && !showing) {
1941 gtk_widget_show(more_arrow_pixmap_button);
1942 showing = TRUE;
1943 } else if (!onoff && showing) {
1944 gtk_widget_hide(more_arrow_pixmap_button);
1945 showing = FALSE;
1946 }
1947}
1948
1949/**********************************************************************/
1955 void real_focus_units_changed(void)
1956{
1957 goto_dialog_focus_units_changed();
1958}
1959
1960/**********************************************************************/
1964 static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev,
1965 gpointer data)
1966{
1967 int i = GPOINTER_TO_INT(data);
1968 struct unit *punit;
1969
1970 if (i == -1) {
1971 punit = game_unit_by_number(unit_id_top);
1972 if (punit && unit_is_in_focus(punit)) {
1973 /* Clicking on the currently selected unit will center it. */
1974 center_tile_mapcanvas(unit_tile(punit));
1975 }
1976 return TRUE;
1977 }
1978
1979 if (unit_ids[i] == 0) /* no unit displayed at this place */
1980 return TRUE;
1981
1982 punit = game_unit_by_number(unit_ids[i]);
1983 if (NULL != punit && unit_owner(punit) == client.conn.playing) {
1984 /* Unit shouldn't be NULL but may be owned by an ally. */
1985 unit_focus_set(punit);
1986 }
1987
1988 return TRUE;
1989}
1990
1991/**********************************************************************/
1995 static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev,
1996 gpointer data)
1997{
1998 struct unit *punit = game_unit_by_number(unit_id_top);
1999
2000 if (punit) {
2001 unit_select_dialog_popup(unit_tile(punit));
2002 }
2003
2004 return TRUE;
2005}
2006
2007/**********************************************************************/
2010 static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data)
2011{
2012 gtk_grab_remove(w);
2013 gdk_device_ungrab(ev->device, ev->time);
2014 gtk_widget_destroy(w);
2015 return FALSE;
2016}
2017
2018/**********************************************************************/
2021 static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
2022{
2023 if (ev->button == 1) {
2024 GtkWidget *p;
2025
2026 p = gtk_window_new(GTK_WINDOW_POPUP);
2027 gtk_container_set_border_width(GTK_CONTAINER(p), 4);
2028 gtk_window_set_transient_for(GTK_WINDOW(p), GTK_WINDOW(toplevel));
2029 gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
2030
2031 gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", p,
2032 "GtkLabel::label", get_info_label_text_popup(),
2033 "GtkWidget::visible", TRUE,
2034 NULL);
2035 gtk_widget_show(p);
2036
2037 gdk_device_grab(ev->device, gtk_widget_get_window(p),
2038 GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_RELEASE_MASK, NULL,
2039 ev->time);
2040 gtk_grab_add(p);
2041
2042 g_signal_connect_after(p, "button_release_event",
2043 G_CALLBACK(show_info_button_release), NULL);
2044 }
2045
2046 return TRUE;
2047}
2048
2049/**********************************************************************/
2052 static void end_turn_callback(GtkWidget *w, gpointer data)
2053{
2054 gtk_widget_set_sensitive(turn_done_button, FALSE);
2055 user_ended_turn();
2056}
2057
2058/**********************************************************************/
2061 static gboolean get_net_input(GIOChannel *source, GIOCondition condition,
2062 gpointer data)
2063{
2064 input_from_server(g_io_channel_unix_get_fd(source));
2065
2066 return TRUE;
2067}
2068
2069/**********************************************************************/
2072 static void set_wait_for_writable_socket(struct connection *pc,
2073 bool socket_writable)
2074{
2075 static bool previous_state = FALSE;
2076
2077 fc_assert_ret(pc == &client.conn);
2078
2079 if (previous_state == socket_writable) {
2080 return;
2081 }
2082
2083 log_debug("set_wait_for_writable_socket(%d)", socket_writable);
2084
2085 g_source_remove(srv_id);
2086 srv_id = g_io_add_watch(srv_channel,
2087 G_IO_IN | (socket_writable ? G_IO_OUT : 0) | G_IO_ERR,
2088 get_net_input,
2089 NULL);
2090
2091 previous_state = socket_writable;
2092}
2093
2094/**********************************************************************/
2098 void add_net_input(int sock)
2099{
2100#ifdef FREECIV_MSWINDOWS
2101 srv_channel = g_io_channel_win32_new_socket(sock);
2102#else
2103 srv_channel = g_io_channel_unix_new(sock);
2104#endif
2105 srv_id = g_io_add_watch(srv_channel,
2106 G_IO_IN | G_IO_ERR,
2107 get_net_input,
2108 NULL);
2109 client.conn.notify_of_writable_data = set_wait_for_writable_socket;
2110}
2111
2112/**********************************************************************/
2116 void remove_net_input(void)
2117{
2118 g_source_remove(srv_id);
2119 g_io_channel_unref(srv_channel);
2120 gdk_window_set_cursor(root_window, NULL);
2121}
2122
2123/**********************************************************************/
2127 static void quit_dialog_response(GtkWidget *dialog, gint response)
2128{
2129 gtk_widget_destroy(dialog);
2130 if (response == GTK_RESPONSE_YES) {
2131 start_quitting();
2132 if (client.conn.used) {
2133 disconnect_from_server();
2134 }
2135 quit_gtk_main();
2136 }
2137}
2138
2139/**********************************************************************/
2142 void quit_gtk_main(void)
2143{
2144 /* Quit gtk main loop. After this it will return to finish
2145 * ui_main() */
2146
2147 gtk_main_quit();
2148}
2149
2150/**********************************************************************/
2154 void popup_quit_dialog(void)
2155{
2156 static GtkWidget *dialog;
2157
2158 if (!dialog) {
2159 dialog = gtk_message_dialog_new(NULL,
2160 0,
2161 GTK_MESSAGE_WARNING,
2162 GTK_BUTTONS_YES_NO,
2163 _("Are you sure you want to quit?"));
2164 setup_dialog(dialog, toplevel);
2165
2166 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
2167
2168 g_signal_connect(dialog, "response",
2169 G_CALLBACK(quit_dialog_response), NULL);
2170 g_signal_connect(dialog, "destroy",
2171 G_CALLBACK(gtk_widget_destroyed), &dialog);
2172 }
2173
2174 gtk_window_present(GTK_WINDOW(dialog));
2175}
2176
2177/**********************************************************************/
2180 static gboolean quit_dialog_callback(void)
2181{
2182 popup_quit_dialog();
2183 /* Stop emission of event. */
2184 return TRUE;
2185}
2186
2187 struct callback {
2188 void (*callback)(void *data);
2189 void *data;
2190};
2191
2192/**********************************************************************/
2195 static gboolean idle_callback_wrapper(gpointer data)
2196{
2197 struct callback *cb = data;
2198
2199 (cb->callback)(cb->data);
2200 free(cb);
2201
2202 return FALSE;
2203}
2204
2205/**********************************************************************/
2210 void add_idle_callback(void (callback)(void *), void *data)
2211{
2212 struct callback *cb = fc_malloc(sizeof(*cb));
2213
2214 cb->callback = callback;
2215 cb->data = data;
2216 g_idle_add(idle_callback_wrapper, cb);
2217}
2218
2219/**********************************************************************/
2223 static void allied_chat_only_callback(struct option *poption)
2224{
2225 GtkWidget *button;
2226
2227 button = allied_chat_toggle_button;
2228 fc_assert_ret(button != NULL);
2229 fc_assert_ret(GTK_IS_TOGGLE_BUTTON(button));
2230
2231 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2232 option_bool_get(poption));
2233}
2234
2235/**********************************************************************/
2238 void fullscreen_opt_refresh(struct option *poption)
2239{
2240 if (GUI_GTK_OPTION(fullscreen)) {
2241 gtk_window_fullscreen(GTK_WINDOW(toplevel));
2242 } else {
2243 gtk_window_unfullscreen(GTK_WINDOW(toplevel));
2244 }
2245}
2246
2247/**********************************************************************/
2250 static void apply_city_names_font(struct option *poption)
2251{
2252 gui_update_font_full(option_font_target(poption),
2253 option_font_get(poption),
2254 &city_names_style);
2255 update_city_descriptions();
2256}
2257
2258/**********************************************************************/
2261 static void apply_city_productions_font(struct option *poption)
2262{
2263 gui_update_font_full(option_font_target(poption),
2264 option_font_get(poption),
2265 &city_productions_style);
2266 update_city_descriptions();
2267}
2268
2269/**********************************************************************/
2272 static void apply_reqtree_text_font(struct option *poption)
2273{
2274 gui_update_font_full(option_font_target(poption),
2275 option_font_get(poption),
2276 &reqtree_text_style);
2277 science_report_dialog_redraw();
2278}
2279
2280/**********************************************************************/
2284 void options_extra_init(void)
2285{
2286 struct option *poption;
2287
2288#define option_var_set_callback(var, callback) \
2289 if ((poption = optset_option_by_name(client_optset, GUI_GTK_OPTION_STR(var)))) { \
2290 option_set_changed_callback(poption, callback); \
2291 } else { \
2292 log_error("Didn't find option %s!", GUI_GTK_OPTION_STR(var)); \
2293 }
2294
2295 option_var_set_callback(allied_chat_only,
2296 allied_chat_only_callback);
2297 option_var_set_callback(fullscreen,
2298 fullscreen_opt_refresh);
2299
2300 option_var_set_callback(font_city_names,
2301 apply_city_names_font);
2302 option_var_set_callback(font_city_productions,
2303 apply_city_productions_font);
2304 option_var_set_callback(font_reqtree_text,
2305 apply_reqtree_text_font);
2306#undef option_var_set_callback
2307}
2308
2309/**********************************************************************/
2313 void refresh_chat_buttons(void)
2314{
2315 GtkWidget *button;
2316
2317 button = allied_chat_toggle_button;
2318 fc_assert_ret(button != NULL);
2319 fc_assert_ret(GTK_IS_TOGGLE_BUTTON(button));
2320
2321 /* Hide the "Allies Only" button for local games. */
2322 if (is_server_running()) {
2323 gtk_widget_hide(button);
2324 } else {
2325 gtk_widget_show(button);
2326 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2327 GUI_GTK_OPTION(allied_chat_only));
2328 }
2329}
2330
2331/**********************************************************************/
2334 static void allied_chat_button_toggled(GtkToggleButton *button,
2335 gpointer user_data)
2336{
2337 GUI_GTK_OPTION(allied_chat_only) = gtk_toggle_button_get_active(button);
2338}
2339
2340/**********************************************************************/
2343 void insert_client_build_info(char *outbuf, size_t outlen)
2344{
2345 cat_snprintf(outbuf, outlen, _("\nBuilt against gtk+ %d.%d.%d, using %d.%d.%d"
2346 "\nBuilt against glib %d.%d.%d, using %d.%d.%d"),
2347 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
2348 gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version(),
2349 GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
2350 glib_major_version, glib_minor_version, glib_micro_version);
2351}
2352
2353/**********************************************************************/
2356 int screen_width(void)
2357{
2358 GdkScreen *screen;
2359
2360 if (vmode.width > 0) {
2361 return vmode.width;
2362 }
2363
2364 screen = gdk_screen_get_default();
2365
2366 if (screen == NULL) {
2367 return 0;
2368 }
2369
2370 return gdk_screen_get_width(screen);
2371}
2372
2373/**********************************************************************/
2376 int screen_height(void)
2377{
2378 GdkScreen *screen;
2379
2380 if (vmode.height > 0) {
2381 return vmode.height;
2382 }
2383
2384 screen = gdk_screen_get_default();
2385
2386 if (screen == NULL) {
2387 return 0;
2388 }
2389
2390 return gdk_screen_get_height(screen);
2391}
2392
2393/**********************************************************************/
2396 struct video_mode *resolution_request_get(void)
2397{
2398 if (vmode.width > 0 && vmode.height > 0) {
2399 return &vmode;
2400 }
2401
2402 return NULL;
2403}
2404
2405/**********************************************************************/
2408 static void adjust_default_options(void)
2409{
2410 int scr_height = screen_height();
2411
2412 if (scr_height > 0) {
2413 /* Adjust these options only if we do know the screen height. */
2414
2415 if (scr_height <= 480) {
2416 /* Freeciv is practically unusable outside fullscreen mode in so
2417 * small display */
2418 log_verbose("Changing default to fullscreen due to very small screen");
2419 GUI_GTK_OPTION(fullscreen) = TRUE;
2420 }
2421 if (scr_height < 1024) {
2422 /* This is a small display */
2423 log_verbose("Defaulting to small widget layout due to small screen");
2424 GUI_GTK_OPTION(small_display_layout) = TRUE;
2425 log_verbose("Defaulting to merged messages/chat due to small screen");
2426 GUI_GTK_OPTION(message_chat_location) = GUI_GTK_MSGCHAT_MERGED;
2427 }
2428 }
2429}
width
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
chat_welcome_message
void chat_welcome_message(bool gui_has_copying_mitem)
Definition chatline_common.c:177
client_is_observer
bool client_is_observer(void)
Definition client_main.c:1086
real_timer_callback
double real_timer_callback(void)
Definition client_main.c:1183
client_main
int client_main(int argc, char *argv[], bool postpone_tileset)
Definition client_main.c:344
user_ended_turn
void user_ended_turn(void)
Definition client_main.c:801
client
struct civclient client
Definition client_main.c:149
start_quitting
void start_quitting(void)
Definition client_main.c:1645
set_client_state
void set_client_state(enum client_states newstate)
Definition client_main.c:847
can_client_change_view
bool can_client_change_view(void)
Definition client_main.c:1313
client_main.h
TIMER_INTERVAL
#define TIMER_INTERVAL
Definition client_main.h:30
C_S_DISCONNECTED
@ C_S_DISCONNECTED
Definition client_main.h:45
buy_production_in_selected_cities
void buy_production_in_selected_cities(void)
Definition climisc.c:1299
client_warming_sprite
struct sprite * client_warming_sprite(void)
Definition climisc.c:371
client_cooling_sprite
struct sprite * client_cooling_sprite(void)
Definition climisc.c:388
client_research_sprite
struct sprite * client_research_sprite(void)
Definition climisc.c:348
client_government_sprite
struct sprite * client_government_sprite(void)
Definition climisc.c:406
climisc.h
input_from_server
void input_from_server(int fd)
Definition clinet.c:406
disconnect_from_server
void disconnect_from_server(void)
Definition clinet.c:305
clinet.h
get_color
struct color * get_color(const struct tileset *t, enum color_std stdcolor)
Definition colors_common.c:100
is_server_running
bool is_server_running(void)
Definition connectdlg_common.c:124
connectdlg_common.h
key_recall_previous_focus_unit
void key_recall_previous_focus_unit(void)
Definition control.c:3134
unit_is_in_focus
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:384
key_cancel_action
void key_cancel_action(void)
Definition control.c:3073
num_units_below
int num_units_below
Definition control.c:76
unit_focus_set
void unit_focus_set(struct unit *punit)
Definition control.c:502
get_units_in_focus
struct unit_list * get_units_in_focus(void)
Definition control.c:177
key_end_turn
void key_end_turn(void)
Definition control.c:3126
update_unit_pix_label
void update_unit_pix_label(struct unit_list *punitlist)
Definition control.c:966
key_unit_move
void key_unit_move(enum direction8 gui_dir)
Definition control.c:3155
hover_state
enum cursor_hover_state hover_state
Definition control.c:89
head_of_units_in_focus
struct unit * head_of_units_in_focus(void)
Definition control.c:406
get_num_units_in_focus
int get_num_units_in_focus(void)
Definition control.c:185
control_mouse_cursor
void control_mouse_cursor(struct tile *ptile)
Definition control.c:1188
key_center_capital
void key_center_capital(void)
Definition control.c:3109
control.h
MAX_NUM_UNITS_BELOW
#define MAX_NUM_UNITS_BELOW
Definition control.h:285
HOVER_NONE
@ HOVER_NONE
Definition control.h:26
dataio.h
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
editor_is_active
bool editor_is_active(void)
Definition editor.c:346
editor.h
event
enum event_type event
Definition events.c:81
is_option
bool is_option(const char *option_name, char *option)
Definition fc_cmdline.c:112
get_option_malloc
char * get_option_malloc(const char *option_name, char **argv, int *i, int argc, bool gc)
Definition fc_cmdline.c:50
fc_cmdline.h
O_SCIENCE
@ O_SCIENCE
Definition fc_types.h:91
O_GOLD
@ O_GOLD
Definition fc_types.h:91
fciconv.h
fc_fprintf
void fc_fprintf(FILE *stream, const char *format,...) fc__attribute((__format__(__printf__
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
_
#define _(String)
Definition fcintl.h:67
featured_text.h
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:111
game.h
government.h
inputline_has_focus
bool inputline_has_focus(void)
Definition chatline.c:71
inputline_toolkit_view_append_button
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1288
inputline_toolkit_view_new
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1266
set_message_buffer_view_link_handlers
void set_message_buffer_view_link_handlers(GtkWidget *view)
Definition chatline.c:744
inputline_is_visible
bool inputline_is_visible(void)
Definition chatline.c:87
chatline_init
void chatline_init(void)
Definition chatline.c:1298
inputline_grab_focus
void inputline_grab_focus(void)
Definition chatline.c:79
chatline_scroll_to_bottom
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1006
citizens_dialog_init
void citizens_dialog_init(void)
Definition citizensinfo.c:267
citizens_dialog_done
void citizens_dialog_done(void)
Definition citizensinfo.c:275
cma_fe_init
void cma_fe_init(void)
Definition cma_fe.c:88
cma_fe_done
void cma_fe_done(void)
Definition cma_fe.c:96
unit_select_dialog_popup
void unit_select_dialog_popup(struct tile *ptile)
Definition dialogs.c:382
taxrates_callback
gboolean taxrates_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition dialogs.c:1434
diplomacy_dialog_init
void diplomacy_dialog_init(void)
Definition diplodlg.c:1173
diplomacy_dialog_done
void diplomacy_dialog_done(void)
Definition diplodlg.c:1182
handle_edit_key_release
gboolean handle_edit_key_release(GdkEventKey *ev)
Definition editgui.c:1779
handle_edit_key_press
gboolean handle_edit_key_press(GdkEventKey *ev)
Definition editgui.c:1661
editgui_create_widgets
void editgui_create_widgets(void)
Definition editgui.c:1821
editgui_get_editbar
struct editbar * editgui_get_editbar(void)
Definition editgui.c:1787
editgui_free
void editgui_free(void)
Definition editgui.c:1834
goto_dialog_focus_units_changed
void goto_dialog_focus_units_changed(void)
Definition gotodlg.c:540
source
static GtkWidget * source
Definition gotodlg.c:58
load_cursors
void load_cursors(void)
Definition graphics.c:78
map_vertical_scrollbar
GtkWidget * map_vertical_scrollbar
Definition gui_main.c:108
ui_main
int ui_main(int argc, char **argv)
Definition gui_main.c:1702
client_string
const char * client_string
Definition gui_main.c:104
message_buffer
GtkTextBuffer * message_buffer
Definition gui_main.c:177
log_gtk_warns
static void log_gtk_warns(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
Definition gui_main.c:276
quit_dialog_response
static void quit_dialog_response(GtkWidget *dialog, gint response)
Definition gui_main.c:2127
real_focus_units_changed
void real_focus_units_changed(void)
Definition gui_main.c:1955
set_unit_icons_more_arrow
void set_unit_icons_more_arrow(bool onoff)
Definition gui_main.c:1932
print_usage
static void print_usage(void)
Definition gui_main.c:249
OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
Definition gui_main.c:115
option_var_set_callback
#define option_var_set_callback(var, callback)
select_unit_image_callback
static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:1964
quit_dialog_callback
static gboolean quit_dialog_callback(void)
Definition gui_main.c:2180
srv_channel
static GIOChannel * srv_channel
Definition gui_main.c:181
main_label_info
GtkWidget * main_label_info
Definition gui_main.c:137
bottom_notebook
GtkWidget * bottom_notebook
Definition gui_main.c:128
unit_info_label
GtkWidget * unit_info_label
Definition gui_main.c:150
timer_callback
static gboolean timer_callback(gpointer data)
Definition gui_main.c:236
resolution_request_get
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2396
set_unit_icon
void set_unit_icon(int idx, struct unit *punit)
Definition gui_main.c:1902
unit_ids
static int unit_ids[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:174
timeout_label
GtkWidget * timeout_label
Definition gui_main.c:147
gui_up
static bool gui_up
Definition gui_main.c:185
srv_id
static guint srv_id
Definition gui_main.c:182
mouse_scroll_mapcanvas
static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
Definition gui_main.c:690
city_productions_style
PangoFontDescription * city_productions_style
Definition gui_main.c:133
overview_scrolled_window
GtkWidget * overview_scrolled_window
Definition gui_main.c:111
more_arrow_pixmap
static GtkWidget * more_arrow_pixmap
Definition gui_main.c:169
detached_widget_fill
static GtkWidget * detached_widget_fill(GtkWidget *tearbox)
Definition gui_main.c:817
enable_menus
void enable_menus(bool enable)
Definition gui_main.c:1001
select_more_arrow_pixmap_callback
static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:1995
top_notebook
GtkWidget * top_notebook
Definition gui_main.c:128
propagate_keypress
static gboolean propagate_keypress(GtkWidget *w, GdkEvent *ev)
Definition gui_main.c:758
MIGRATE_STR_OPTION
#define MIGRATE_STR_OPTION(opt)
econ_ebox
GtkWidget * econ_ebox
Definition gui_main.c:154
unit_info_box
GtkWidget * unit_info_box
Definition gui_main.c:151
ui_exit
void ui_exit(void)
Definition gui_main.c:1872
get_gui_type
enum gui_type get_gui_type(void)
Definition gui_main.c:1883
detached_widget_new
static GtkWidget * detached_widget_new(void)
Definition gui_main.c:805
cur_y
gint cur_y
Definition gui_main.c:183
main
int main(int argc, char **argv)
Definition gui_main.c:1627
fullscreen_opt_refresh
void fullscreen_opt_refresh(struct option *poption)
Definition gui_main.c:2238
main_message_area_size_allocate
static void main_message_area_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Definition gui_main.c:349
toplevel_handler
static gboolean toplevel_handler(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:383
ui_init
void ui_init(void)
Definition gui_main.c:1618
unit_below_image_button
static GtkWidget * unit_below_image_button[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:168
free_unit_table
static void free_unit_table(void)
Definition gui_main.c:944
idle_callback_wrapper
static gboolean idle_callback_wrapper(gpointer data)
Definition gui_main.c:2195
apply_city_names_font
static void apply_city_names_font(struct option *poption)
Definition gui_main.c:2250
apply_city_productions_font
static void apply_city_productions_font(struct option *poption)
Definition gui_main.c:2261
unit_below_image
static GtkWidget * unit_below_image[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:167
tearoff_destroy
static void tearoff_destroy(GtkWidget *w, gpointer data)
Definition gui_main.c:742
government_label
GtkWidget * government_label
Definition gui_main.c:146
sun_label
GtkWidget * sun_label
Definition gui_main.c:144
city_names_style
PangoFontDescription * city_names_style
Definition gui_main.c:132
refresh_chat_buttons
void refresh_chat_buttons(void)
Definition gui_main.c:2313
map_canvas_focus
gboolean map_canvas_focus(void)
Definition gui_main.c:366
turn_done_button
GtkWidget * turn_done_button
Definition gui_main.c:148
bottom_hpaned
static GtkWidget * bottom_hpaned
Definition gui_main.c:130
timer_id
static gint timer_id
Definition gui_main.c:180
main_menubar
static GtkWidget * main_menubar
Definition gui_main.c:163
screen_width
int screen_width(void)
Definition gui_main.c:2356
scroll_panel
GtkWidget * scroll_panel
Definition gui_main.c:140
end_turn_callback
static void end_turn_callback(GtkWidget *w, gpointer data)
Definition gui_main.c:2052
OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
Definition gui_main.c:116
log_callback_utf8
static void log_callback_utf8(enum log_level level, const char *message, bool file_too)
Definition gui_main.c:224
add_idle_callback
void add_idle_callback(void(callback)(void *), void *data)
Definition gui_main.c:2210
show_info_popup
static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition gui_main.c:2021
reset_unit_table
void reset_unit_table(void)
Definition gui_main.c:972
key_press_map_canvas
static gboolean key_press_map_canvas(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:407
unit_info_frame
GtkWidget * unit_info_frame
Definition gui_main.c:152
options_extra_init
void options_extra_init(void)
Definition gui_main.c:2284
top_vbox
GtkWidget * top_vbox
Definition gui_main.c:127
allied_chat_only_callback
static void allied_chat_only_callback(struct option *poption)
Definition gui_main.c:2223
root_window
GdkWindow * root_window
Definition gui_main.c:125
adjust_default_options
static void adjust_default_options(void)
Definition gui_main.c:2408
set_wait_for_writable_socket
static void set_wait_for_writable_socket(struct connection *pc, bool socket_writable)
Definition gui_main.c:2072
more_arrow_pixmap_button
static GtkWidget * more_arrow_pixmap_button
Definition gui_main.c:170
ahbox
GtkWidget * ahbox
Definition gui_main.c:139
apply_reqtree_text_font
static void apply_reqtree_text_font(struct option *poption)
Definition gui_main.c:2272
show_info_button_release
static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition gui_main.c:2010
is_gui_up
bool is_gui_up(void)
Definition gui_main.c:1864
toplevel_focus
static gboolean toplevel_focus(GtkWidget *w, GtkDirectionType arg)
Definition gui_main.c:322
reqtree_text_style
PangoFontDescription * reqtree_text_style
Definition gui_main.c:134
sun_ebox
GtkWidget * sun_ebox
Definition gui_main.c:156
bulb_ebox
GtkWidget * bulb_ebox
Definition gui_main.c:155
flake_label
GtkWidget * flake_label
Definition gui_main.c:145
avbox
GtkWidget * avbox
Definition gui_main.c:139
cur_x
gint cur_x
Definition gui_main.c:183
insert_client_build_info
void insert_client_build_info(char *outbuf, size_t outlen)
Definition gui_main.c:2343
unit_image_button
static GtkWidget * unit_image_button
Definition gui_main.c:166
unit_image_table
static GtkWidget * unit_image_table
Definition gui_main.c:164
right_notebook_button_release
static gboolean right_notebook_button_release(GtkWidget *widget, GdkEventButton *event)
Definition gui_main.c:1024
bulb_label
GtkWidget * bulb_label
Definition gui_main.c:143
overview_canvas
GtkWidget * overview_canvas
Definition gui_main.c:110
toplevel
GtkWidget * toplevel
Definition gui_main.c:124
setup_widgets
static void setup_widgets(void)
Definition gui_main.c:1074
OVERVIEW_CANVAS_STORE_WIDTH
#define OVERVIEW_CANVAS_STORE_WIDTH
Definition gui_main.c:117
toplevel_key_release_handler
static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:588
remove_net_input
void remove_net_input(void)
Definition gui_main.c:2116
map_horizontal_scrollbar
GtkWidget * map_horizontal_scrollbar
Definition gui_main.c:107
setup_canvas_color_for_state
static void setup_canvas_color_for_state(GtkStateFlags state)
Definition gui_main.c:1044
map_canvas
GtkWidget * map_canvas
Definition gui_main.c:106
toplevel_key_press_handler
static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:606
sound_bell
void sound_bell(void)
Definition gui_main.c:1891
migrate_options_from_gtk2
static void migrate_options_from_gtk2(void)
Definition gui_main.c:1635
econ_label
GtkWidget * econ_label[10]
Definition gui_main.c:142
government_ebox
GtkWidget * government_ebox
Definition gui_main.c:158
migrate_options_from_2_5
static void migrate_options_from_2_5(void)
Definition gui_main.c:1690
popup_quit_dialog
void popup_quit_dialog(void)
Definition gui_main.c:2154
gui_character_encoding
const char *const gui_character_encoding
Definition gui_main.c:160
unit_id_top
static int unit_id_top
Definition gui_main.c:173
get_net_input
static gboolean get_net_input(GIOChannel *source, GIOCondition condition, gpointer data)
Definition gui_main.c:2061
more_arrow_pixmap_container
static GtkWidget * more_arrow_pixmap_container
Definition gui_main.c:171
map_widget
GtkWidget * map_widget
Definition gui_main.c:129
right_notebook
GtkWidget * right_notebook
Definition gui_main.c:128
quit_gtk_main
void quit_gtk_main(void)
Definition gui_main.c:2142
allied_chat_button_toggled
static void allied_chat_button_toggled(GtkToggleButton *button, gpointer user_data)
Definition gui_main.c:2334
vmode
static struct video_mode vmode
Definition gui_main.c:187
add_net_input
void add_net_input(int sock)
Definition gui_main.c:2098
toplevel_tabs
GtkWidget * toplevel_tabs
Definition gui_main.c:126
allied_chat_toggle_button
static GtkWidget * allied_chat_toggle_button
Definition gui_main.c:178
flake_ebox
GtkWidget * flake_ebox
Definition gui_main.c:157
overview_canvas_store_width
int overview_canvas_store_width
Definition gui_main.c:121
update_turn_done_tooltip
void update_turn_done_tooltip(void)
Definition gui_main.c:1055
tearoff_callback
static void tearoff_callback(GtkWidget *b, gpointer data)
Definition gui_main.c:769
unit_image
static GtkWidget * unit_image
Definition gui_main.c:165
main_message_area
GtkTextView * main_message_area
Definition gui_main.c:176
overview_canvas_store_height
int overview_canvas_store_height
Definition gui_main.c:122
screen_height
int screen_height(void)
Definition gui_main.c:2376
parse_options
static bool parse_options(int argc, char **argv)
Definition gui_main.c:286
conn_box
GtkWidget * conn_box
Definition gui_main.c:139
OVERVIEW_CANVAS_STORE_HEIGHT
#define OVERVIEW_CANVAS_STORE_HEIGHT
Definition gui_main.c:119
main_frame_civ_name
GtkWidget * main_frame_civ_name
Definition gui_main.c:136
MIGRATE_OPTION
#define MIGRATE_OPTION(opt)
gui_use_transliteration
const bool gui_use_transliteration
Definition gui_main.c:161
populate_unit_image_table
static void populate_unit_image_table(void)
Definition gui_main.c:842
GUI_NAME_FULL
#define GUI_NAME_FULL
Definition gui_main.h:22
GUI_NAME_SHORT
#define GUI_NAME_SHORT
Definition gui_main.h:23
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
gui_update_font_full
void gui_update_font_full(const char *font_name, const char *font_value, PangoFontDescription **font_desc)
Definition gui_stuff.c:1070
happiness_dialog_init
void happiness_dialog_init(void)
Definition happiness.c:86
happiness_dialog_done
void happiness_dialog_done(void)
Definition happiness.c:94
help_system_init
void help_system_init(void)
Definition helpdlg.c:156
intel_dialog_done
void intel_dialog_done(void)
Definition inteldlg.c:127
intel_dialog_init
void intel_dialog_init(void)
Definition inteldlg.c:118
luaconsole_dialog_init
void luaconsole_dialog_init(void)
Definition luaconsole.c:83
luaconsole_dialog_done
void luaconsole_dialog_done(void)
Definition luaconsole.c:101
butt_release_mapcanvas
gboolean butt_release_mapcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:216
move_overviewcanvas
gboolean move_overviewcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:458
butt_down_overviewcanvas
gboolean butt_down_overviewcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:467
butt_down_mapcanvas
gboolean butt_down_mapcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:237
move_mapcanvas
gboolean move_mapcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:400
leave_mapcanvas
gboolean leave_mapcanvas(GtkWidget *widget, GdkEventCrossing *event)
Definition mapctrl.c:429
update_city_descriptions
void update_city_descriptions(void)
Definition mapview.c:470
map_canvas_draw
gboolean map_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:407
map_canvas_configure
gboolean map_canvas_configure(GtkWidget *w, GdkEventConfigure *ev, gpointer data)
Definition mapview.c:386
put_unit_image
void put_unit_image(struct unit *punit, GtkImage *p, int height)
Definition mapview.c:478
overview_canvas_draw
gboolean overview_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:339
setup_menus
GtkWidget * setup_menus(GtkWidget *window)
Definition menu.c:2115
menus_free
void menus_free(void)
Definition menu.c:3138
meswin_dialog_popup
void meswin_dialog_popup(bool raise)
Definition messagewin.c:416
create_start_page
GtkWidget * create_start_page(void)
Definition pages.c:2619
create_network_page
GtkWidget * create_network_page(void)
Definition pages.c:1197
create_scenario_page
GtkWidget * create_scenario_page(void)
Definition pages.c:3182
statusbar
static GtkWidget * statusbar
Definition pages.c:89
destroy_server_scans
void destroy_server_scans(void)
Definition pages.c:765
create_load_page
GtkWidget * create_load_page(void)
Definition pages.c:2900
create_statusbar
GtkWidget * create_statusbar(void)
Definition pages.c:906
create_main_page
GtkWidget * create_main_page(void)
Definition pages.c:229
science_report_dialog_redraw
void science_report_dialog_redraw(void)
Definition repodlgs.c:761
spaceship_dialog_init
void spaceship_dialog_init(void)
Definition spaceshipdlg.c:87
spaceship_dialog_done
void spaceship_dialog_done(void)
Definition spaceshipdlg.c:95
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
ingame_votebar
GtkWidget * ingame_votebar
Definition voteinfo_bar.c:50
voteinfo_bar_new
GtkWidget * voteinfo_bar_new(bool split_bar)
Definition voteinfo_bar.c:92
citizensinfo.h
editgui.h
gui_stuff.h
happiness.h
cma_fe.h
chatline.h
colors.h
connectdlg.h
dialogs.h
diplodlg.h
gotodlg.h
graphics.h
gui_main.h
helpdlg.h
inteldlg.h
luaconsole.h
mapctrl.h
mapview.h
menu.h
messagewin.h
optiondlg.h
pages.h
plrdlg.h
repodlgs.h
spaceshipdlg.h
voteinfo_bar.h
log_set_callback
log_callback_fn log_set_callback(log_callback_fn callback)
Definition log.c:290
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_verbose
#define log_verbose(message,...)
Definition log.h:109
log_fatal
#define log_fatal(message,...)
Definition log.h:100
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
log_level
log_level
Definition log.h:28
LOG_FATAL
@ LOG_FATAL
Definition log.h:29
log_error
#define log_error(message,...)
Definition log.h:103
map.h
update_line
void update_line(int canvas_x, int canvas_y)
Definition mapctrl_common.c:662
maybe_activate_keyboardless_goto
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
Definition mapctrl_common.c:504
rbutton_down
bool rbutton_down
Definition mapctrl_common.c:55
tiles_hilited_cities
bool tiles_hilited_cities
Definition mapctrl_common.c:60
scroll_mapview
void scroll_mapview(enum direction8 gui_dir)
Definition mapctrl_common.c:549
keyboardless_goto_button_down
bool keyboardless_goto_button_down
Definition mapctrl_common.c:69
update_selection_rectangle
void update_selection_rectangle(float canvas_x, float canvas_y)
Definition mapctrl_common.c:201
init_mapcanvas_and_overview
void init_mapcanvas_and_overview(void)
Definition mapview_common.c:3684
canvas_pos_to_tile
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y, float zoom)
Definition mapview_common.c:751
free_mapcanvas_and_overview
void free_mapcanvas_and_overview(void)
Definition mapview_common.c:3693
get_mapview_scroll_pos
void get_mapview_scroll_pos(int *scroll_x, int *scroll_y)
Definition mapview_common.c:1191
get_mapview_scroll_step
void get_mapview_scroll_step(int *xstep, int *ystep)
Definition mapview_common.c:1177
set_mapview_scroll_pos
void set_mapview_scroll_pos(int scroll_x, int scroll_y, float zoom)
Definition mapview_common.c:1200
center_tile_mapcanvas
void center_tile_mapcanvas(const struct tile *ptile)
Definition mapview_common.c:1222
set_frame_by_frame_animation
void set_frame_by_frame_animation(void)
Definition mapview_common.c:4082
link_marks_clear_all
void link_marks_clear_all(void)
Definition mapview_common.c:3953
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
menus_init
void menus_init(void)
Definition update_queue.c:554
option_changed
void option_changed(struct option *poption)
Definition options.c:723
server_optset
const struct option_set * server_optset
Definition options.c:4009
client_optset
const struct option_set * client_optset
Definition options.c:1255
option_bool_get
bool option_bool_get(const struct option *poption)
Definition options.c:772
option_type
enum option_type option_type(const struct option *poption)
Definition options.c:633
option_font_target
const char * option_font_target(const struct option *poption)
Definition options.c:1138
string_to_video_mode
bool string_to_video_mode(const char *buf, struct video_mode *mode)
Definition options.c:6453
gui_options
struct client_options gui_options
Definition options.c:71
option_font_get
const char * option_font_get(const struct option *poption)
Definition options.c:1116
optset_option_by_name
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:406
options.h
GUI_GTK_OVERVIEW_MIN_XSIZE
#define GUI_GTK_OVERVIEW_MIN_XSIZE
Definition options.h:574
options_iterate
#define options_iterate(poptset, poption)
Definition options.h:527
GUI_GTK_MSGCHAT_MERGED
@ GUI_GTK_MSGCHAT_MERGED
Definition options.h:68
GUI_GTK_MSGCHAT_SPLIT
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:66
options_iterate_end
#define options_iterate_end
Definition options.h:532
get_info_label_text_popup
const char * get_info_label_text_popup(void)
Definition text.c:1002
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
callback
Definition gui_main.c:2187
callback::data
void * data
Definition gui_main.c:2189
callback::callback
void(* callback)(void *data)
Definition gui_main.c:2188
civclient::conn
struct connection conn
Definition client_main.h:96
client_options::sound_effects_volume
int sound_effects_volume
Definition options.h:183
client_options::first_boot
bool first_boot
Definition options.h:124
client_options::migrate_fullscreen
bool migrate_fullscreen
Definition options.h:138
color
Definition colors.h:20
connection
Definition connection.h:141
connection::playing
struct player * playing
Definition connection.h:156
connection::notify_of_writable_data
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition connection.h:186
connection::used
bool used
Definition connection.h:144
message
Definition messagewin_common.h:29
option
Definition options.c:454
sprite
Definition sprite.h:22
sprite::surface
cairo_surface_t * surface
Definition sprite.h:23
tileset
Definition tilespec.c:459
unit
Definition unit.h:138
unit::id
int id
Definition unit.h:145
video_mode
Definition options.h:45
video_mode::height
int height
Definition options.h:47
video_mode::width
int width
Definition options.h:46
view
Definition mapview_common.h:36
widget
Definition widget.h:112
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
text.h
tileset_load_tiles
void tileset_load_tiles(struct tileset *t)
Definition tilespec.c:3452
tileset_free_tiles
void tileset_free_tiles(struct tileset *t)
Definition tilespec.c:6346
tileset_use_preferred_theme
void tileset_use_preferred_theme(const struct tileset *t)
Definition tilespec.c:6768
get_icon_sprite
struct sprite * get_icon_sprite(const struct tileset *t, enum icon_type icon)
Definition tilespec.c:6678
tileset_init
void tileset_init(struct tileset *t)
Definition tilespec.c:6827
get_arrow_sprite
struct sprite * get_arrow_sprite(const struct tileset *t, enum arrow_type arrow)
Definition tilespec.c:6568
get_tax_sprite
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:6579
tileset_tile_width
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:716
tilespec.h
ARROW_RIGHT
@ ARROW_RIGHT
Definition tilespec.h:199
ICON_FREECIV
@ ICON_FREECIV
Definition tilespec.h:310
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
unitlist.h
version.h
enable
#define enable(id)
Definition widget.h:223
mouse_zoom
float mouse_zoom
Definition zoom.c:28
zoom_step_down
void zoom_step_down(void)
Definition zoom.c:130
zoom_step_up
void zoom_step_up(void)
Definition zoom.c:106
zoom.h