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

Freeciv-3.1

Loading...
Searching...
No Matches
messagewin.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#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include <gtk/gtk.h>
23
24/* utility */
25#include "fcintl.h"
26#include "log.h"
27
28/* common */
29#include "events.h"
30#include "game.h"
31#include "map.h"
32#include "player.h"
33
34/* client */
35#include "options.h"
36
37/* client/gui-gtk-4.0 */
38#include "chatline.h"
39#include "citydlg.h"
40#include "gui_main.h"
41#include "gui_stuff.h"
42#include "mapview.h"
43
44#include "messagewin.h"
45
46
47struct meswin_dialog {
48 struct gui_dialog *shell;
49 GtkTreeView *tree_view;
50};
51
52/* Those values must match meswin_dialog_store_new(). */
53 enum meswin_columns {
54 MESWIN_COL_ICON,
55 MESWIN_COL_MESSAGE,
56
57 /* Not visible. */
58 MESWIN_COL_WEIGHT,
59 MESWIN_COL_STYLE,
60 MESWIN_COL_ID,
61
62 MESWIN_COL_NUM
63};
64
65 enum meswin_responses {
66 MESWIN_RES_GOTO = 1,
67 MESWIN_RES_POPUP_CITY
68};
69
70 static struct meswin_dialog meswin = { NULL, };
71
72/************************************************************************/
75 static GtkListStore *meswin_dialog_store_new(void)
76{
77 return gtk_list_store_new(MESWIN_COL_NUM,
78 GDK_TYPE_PIXBUF, /* MESWIN_COL_ICON */
79 G_TYPE_STRING, /* MESWIN_COL_MESSAGE */
80 G_TYPE_INT, /* MESWIN_COL_WEIGHT */
81 G_TYPE_INT, /* MESWIN_COL_STYLE */
82 G_TYPE_INT); /* MESWIN_COL_ID */
83}
84
85/************************************************************************/
88 static void meswin_dialog_visited_get_attr(bool visited, gint *weight,
89 gint *style)
90{
91 if (NULL != weight) {
92 *weight = (visited ? PANGO_WEIGHT_NORMAL : PANGO_WEIGHT_BOLD);
93 }
94 if (NULL != style) {
95 *style = (visited ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
96 }
97}
98
99/************************************************************************/
102 static void meswin_dialog_set_visited(GtkTreeModel *model,
103 GtkTreeIter *iter, bool visited)
104{
105 gint row, weight, style;
106
107 gtk_tree_model_get(model, iter, MESWIN_COL_ID, &row, -1);
108 meswin_dialog_visited_get_attr(visited, &weight, &style);
109 gtk_list_store_set(GTK_LIST_STORE(model), iter,
110 MESWIN_COL_WEIGHT, weight,
111 MESWIN_COL_STYLE, style,
112 -1);
113 meswin_set_visited_state(row, visited);
114}
115
116/************************************************************************/
119 static void meswin_dialog_refresh(struct meswin_dialog *pdialog)
120{
121 GtkTreeSelection *selection;
122 GtkTreeModel *model;
123 GtkListStore *store;
124 GtkTreeIter iter;
125 const struct message *pmsg;
126 gint weight, style;
127 int selected, i, num;
128 bool need_alert = FALSE;
129
130 fc_assert_ret(NULL != pdialog);
131
132 /* Save the selection. */
133 selection = gtk_tree_view_get_selection(pdialog->tree_view);
134 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
135 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &selected, -1);
136 } else {
137 selected = -1;
138 }
139
140 model = gtk_tree_view_get_model(pdialog->tree_view);
141 store = GTK_LIST_STORE(model);
142 num = meswin_get_num_messages();
143
144 gtk_list_store_clear(store);
145 for (i = 0; i < num; i++) {
146 GdkPixbuf *pb;
147 struct sprite *icon;
148 int x0, y0, x1, y1, w, h;
149 GdkPixbuf *pixbuf;
150
151 pmsg = meswin_get_message(i);
152
153 if (GUI_GTK_OPTION(new_messages_go_to_top)) {
154 gtk_list_store_prepend(store, &iter);
155 } else {
156 gtk_list_store_append(store, &iter);
157 }
158
159 icon = get_event_sprite(tileset, pmsg->event);
160 sprite_get_bounding_box(icon, &x0, &y0, &x1, &y1);
161 w = (x1 - x0) + 1;
162 h = (y1 - y0) + 1;
163 pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
164 pixbuf = sprite_get_pixbuf(icon);
165 gdk_pixbuf_copy_area(pixbuf, x0, y0, w, h,
166 pb, 0, 0);
167 g_object_unref(G_OBJECT(pixbuf));
168
169 meswin_dialog_visited_get_attr(pmsg->visited, &weight, &style);
170 gtk_list_store_set(store, &iter,
171 MESWIN_COL_ICON, pb,
172 MESWIN_COL_MESSAGE, pmsg->descr,
173 MESWIN_COL_WEIGHT, weight,
174 MESWIN_COL_STYLE, style,
175 MESWIN_COL_ID, i,
176 -1);
177 g_object_unref(pb);
178 if (i == selected) {
179 /* Restore the selection. */
180 gtk_tree_selection_select_iter(selection, &iter);
181 }
182
183 if (!pmsg->visited) {
184 need_alert = TRUE;
185 }
186 }
187
188 if (need_alert) {
189 gui_dialog_alert(pdialog->shell);
190 }
191}
192
193/************************************************************************/
196 static void meswin_dialog_selection_callback(GtkTreeSelection *selection,
197 gpointer data)
198{
199 struct meswin_dialog *pdialog = data;
200 const struct message *pmsg;
201 GtkTreeModel *model;
202 GtkTreeIter iter;
203 gint row;
204
205 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
206 return;
207 }
208
209 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
210 pmsg = meswin_get_message(row);
211
212 gui_dialog_set_response_sensitive(pdialog->shell, MESWIN_RES_GOTO,
213 NULL != pmsg && pmsg->location_ok);
214 gui_dialog_set_response_sensitive(pdialog->shell, MESWIN_RES_POPUP_CITY,
215 NULL != pmsg && pmsg->city_ok);
216}
217
218/************************************************************************/
221 static void meswin_dialog_row_activated_callback(GtkTreeView *view,
222 GtkTreePath *path,
223 GtkTreeViewColumn *col,
224 gpointer data)
225{
226 GtkTreeModel *model = gtk_tree_view_get_model(view);
227 GtkTreeIter iter;
228 gint row;
229
230 if (!gtk_tree_model_get_iter(model, &iter, path)) {
231 return;
232 }
233
234 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
235
236 if (NULL != meswin_get_message(row)) {
237 meswin_double_click(row);
238 meswin_dialog_set_visited(model, &iter, TRUE);
239 }
240}
241
242/************************************************************************/
247 static gboolean meswin_dialog_button_press_callback(GtkGestureClick *gesture,
248 int n_press,
249 double x, double y)
250{
251 GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
252 GtkTreePath *path = NULL;
253 GtkTreeModel *model;
254 GtkTreeIter iter;
255 gint row;
256
257 fc_assert_ret_val(GTK_IS_TREE_VIEW(widget), FALSE);
258
259 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y,
260 &path, NULL, NULL, NULL)) {
261 return TRUE;
262 }
263
264 model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
265 if (gtk_tree_model_get_iter(model, &iter, path)) {
266 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
267 meswin_goto(row);
268 }
269
270 gtk_tree_path_free(path);
271
272 return TRUE;
273}
274
275/************************************************************************/
278 static void meswin_dialog_response_callback(struct gui_dialog *pgui_dialog,
279 int response, gpointer data)
280{
281 struct meswin_dialog *pdialog = data;
282 GtkTreeSelection *selection;
283 GtkTreeModel *model;
284 GtkTreeIter iter;
285 gint row;
286
287 switch (response) {
288 case MESWIN_RES_GOTO:
289 case MESWIN_RES_POPUP_CITY:
290 break;
291 default:
292 gui_dialog_destroy(pgui_dialog);
293 return;
294 }
295
296 selection = gtk_tree_view_get_selection(pdialog->tree_view);
297 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
298 return;
299 }
300
301 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
302
303 switch (response) {
304 case MESWIN_RES_GOTO:
305 meswin_goto(row);
306 break;
307 case MESWIN_RES_POPUP_CITY:
308 meswin_popup_city(row);
309 break;
310 }
311 meswin_dialog_set_visited(model, &iter, TRUE);
312}
313
314/************************************************************************/
317 static void meswin_dialog_init(struct meswin_dialog *pdialog)
318{
319 GtkWidget *view, *sw, *cmd, *notebook;
320 GtkListStore *store;
321 GtkTreeSelection *selection;
322 GtkCellRenderer *renderer;
323 GtkTreeViewColumn *col;
324 GtkGesture *gesture;
325 GtkEventController *controller;
326
327 fc_assert_ret(NULL != pdialog);
328
329 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
330 notebook = right_notebook;
331 } else {
332 notebook = bottom_notebook;
333 }
334
335 gui_dialog_new(&pdialog->shell, GTK_NOTEBOOK(notebook), pdialog, TRUE);
336 gui_dialog_set_title(pdialog->shell, _("Messages"));
337
338 sw = gtk_scrolled_window_new();
339 gtk_scrolled_window_set_has_frame(GTK_SCROLLED_WINDOW(sw), TRUE);
340 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
341 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
342 gui_dialog_add_content_widget(pdialog->shell, sw);
343
344 store = meswin_dialog_store_new();
345 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
346 gtk_widget_set_hexpand(view, TRUE);
347 gtk_widget_set_vexpand(view, TRUE);
348 g_object_unref(store);
349 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(view));
350 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
351 g_signal_connect(view, "row_activated",
352 G_CALLBACK(meswin_dialog_row_activated_callback), NULL);
353
354 gesture = gtk_gesture_click_new();
355 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 3);
356 controller = GTK_EVENT_CONTROLLER(gesture);
357 g_signal_connect(controller, "pressed",
358 G_CALLBACK(meswin_dialog_button_press_callback), NULL);
359 gtk_widget_add_controller(view, controller);
360
361 pdialog->tree_view = GTK_TREE_VIEW(view);
362
363 renderer = gtk_cell_renderer_pixbuf_new();
364 col = gtk_tree_view_column_new_with_attributes(NULL, renderer,
365 "pixbuf", MESWIN_COL_ICON, NULL);
366 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
367 gtk_tree_view_column_set_visible(col, !GUI_GTK_OPTION(small_display_layout));
368
369 renderer = gtk_cell_renderer_text_new();
370 col = gtk_tree_view_column_new_with_attributes(NULL, renderer,
371 "text", MESWIN_COL_MESSAGE,
372 "weight", MESWIN_COL_WEIGHT,
373 "style", MESWIN_COL_STYLE,
374 NULL);
375 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
376 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), view);
377
378 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
379 g_signal_connect(selection, "changed",
380 G_CALLBACK(meswin_dialog_selection_callback), pdialog);
381
382 gui_dialog_add_button(pdialog->shell, "window-close", _("_Close"),
383 GTK_RESPONSE_CLOSE);
384
385 if (GUI_GTK_OPTION(show_message_window_buttons)) {
386 cmd = gui_dialog_add_button(pdialog->shell, "zoom-in",
387 _("I_nspect City"),
388 MESWIN_RES_POPUP_CITY);
389 gtk_widget_set_sensitive(cmd, FALSE);
390
391 cmd = gui_dialog_add_button(pdialog->shell, "go-jump",
392 _("Goto _Location"), MESWIN_RES_GOTO);
393 gtk_widget_set_sensitive(cmd, FALSE);
394 }
395
396 gui_dialog_response_set_callback(pdialog->shell,
397 meswin_dialog_response_callback);
398 gui_dialog_set_default_size(pdialog->shell, 520, 300);
399
400 meswin_dialog_refresh(pdialog);
401 gui_dialog_show_all(pdialog->shell);
402}
403
404/************************************************************************/
407 static void meswin_dialog_free(struct meswin_dialog *pdialog)
408{
409 fc_assert_ret(NULL != pdialog);
410
411 gui_dialog_destroy(pdialog->shell);
412 fc_assert(NULL == pdialog->shell);
413
414 memset(pdialog, 0, sizeof(*pdialog));
415}
416
417/************************************************************************/
420 void meswin_dialog_popup(bool raise)
421{
422 if (NULL == meswin.shell) {
423 meswin_dialog_init(&meswin);
424 }
425
426 gui_dialog_present(meswin.shell);
427 if (raise) {
428 gui_dialog_raise(meswin.shell);
429 }
430}
431
432/************************************************************************/
435 void meswin_dialog_popdown(void)
436{
437 if (NULL != meswin.shell) {
438 meswin_dialog_free(&meswin);
439 fc_assert(NULL == meswin.shell);
440 }
441}
442
443/************************************************************************/
446 bool meswin_dialog_is_open(void)
447{
448 return (NULL != meswin.shell);
449}
450
451/************************************************************************/
454 void real_meswin_dialog_update(void *unused)
455{
456 if (NULL != meswin.shell) {
457 meswin_dialog_refresh(&meswin);
458 }
459}
events.h
fcintl.h
_
#define _(String)
Definition fcintl.h:67
game.h
bottom_notebook
GtkWidget * bottom_notebook
Definition gui_main.c:128
right_notebook
GtkWidget * right_notebook
Definition gui_main.c:128
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
gui_dialog_destroy
void gui_dialog_destroy(struct gui_dialog *dlg)
Definition gui_stuff.c:951
gui_dialog_present
void gui_dialog_present(struct gui_dialog *dlg)
Definition gui_stuff.c:834
gui_dialog_raise
void gui_dialog_raise(struct gui_dialog *dlg)
Definition gui_stuff.c:864
gui_dialog_new
void gui_dialog_new(struct gui_dialog **pdlg, GtkNotebook *notebook, gpointer user_data, bool check_top)
Definition gui_stuff.c:504
gui_dialog_response_set_callback
void gui_dialog_response_set_callback(struct gui_dialog *dlg, GUI_DIALOG_RESPONSE_FUN fun)
Definition gui_stuff.c:985
gui_dialog_add_button
GtkWidget * gui_dialog_add_button(struct gui_dialog *dlg, const char *text, int response)
Definition gui_stuff.c:706
gui_dialog_show_all
void gui_dialog_show_all(struct gui_dialog *dlg)
Definition gui_stuff.c:794
gui_dialog_set_title
void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
Definition gui_stuff.c:932
gui_dialog_set_default_size
void gui_dialog_set_default_size(struct gui_dialog *dlg, int width, int height)
Definition gui_stuff.c:916
gui_dialog_alert
void gui_dialog_alert(struct gui_dialog *dlg)
Definition gui_stuff.c:887
gui_dialog_set_response_sensitive
void gui_dialog_set_response_sensitive(struct gui_dialog *dlg, int response, bool setting)
Definition gui_stuff.c:759
meswin_dialog_init
static void meswin_dialog_init(struct meswin_dialog *pdialog)
Definition messagewin.c:319
meswin_dialog_button_press_callback
static gboolean meswin_dialog_button_press_callback(GtkWidget *widget, GdkEventButton *ev, gpointer data)
Definition messagewin.c:247
meswin_dialog_popdown
void meswin_dialog_popdown(void)
Definition messagewin.c:431
meswin_dialog_visited_get_attr
static void meswin_dialog_visited_get_attr(bool visited, gint *weight, gint *style)
Definition messagewin.c:88
meswin_dialog_row_activated_callback
static void meswin_dialog_row_activated_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition messagewin.c:221
meswin_dialog_set_visited
static void meswin_dialog_set_visited(GtkTreeModel *model, GtkTreeIter *iter, bool visited)
Definition messagewin.c:102
meswin
static struct meswin_dialog meswin
Definition messagewin.c:70
meswin_dialog_store_new
static GtkListStore * meswin_dialog_store_new(void)
Definition messagewin.c:75
meswin_dialog_response_callback
static void meswin_dialog_response_callback(struct gui_dialog *pgui_dialog, int response, gpointer data)
Definition messagewin.c:280
meswin_dialog_popup
void meswin_dialog_popup(bool raise)
Definition messagewin.c:416
meswin_dialog_refresh
static void meswin_dialog_refresh(struct meswin_dialog *pdialog)
Definition messagewin.c:119
meswin_columns
meswin_columns
Definition messagewin.c:53
MESWIN_COL_NUM
@ MESWIN_COL_NUM
Definition messagewin.c:62
MESWIN_COL_MESSAGE
@ MESWIN_COL_MESSAGE
Definition messagewin.c:55
MESWIN_COL_STYLE
@ MESWIN_COL_STYLE
Definition messagewin.c:59
MESWIN_COL_ID
@ MESWIN_COL_ID
Definition messagewin.c:60
MESWIN_COL_ICON
@ MESWIN_COL_ICON
Definition messagewin.c:54
MESWIN_COL_WEIGHT
@ MESWIN_COL_WEIGHT
Definition messagewin.c:58
meswin_responses
meswin_responses
Definition messagewin.c:65
MESWIN_RES_GOTO
@ MESWIN_RES_GOTO
Definition messagewin.c:66
MESWIN_RES_POPUP_CITY
@ MESWIN_RES_POPUP_CITY
Definition messagewin.c:67
meswin_dialog_free
static void meswin_dialog_free(struct meswin_dialog *pdialog)
Definition messagewin.c:403
meswin_dialog_selection_callback
static void meswin_dialog_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition messagewin.c:196
real_meswin_dialog_update
void real_meswin_dialog_update(void *unused)
Definition messagewin.c:450
meswin_dialog_is_open
bool meswin_dialog_is_open(void)
Definition messagewin.c:442
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
sprite_get_bounding_box
void sprite_get_bounding_box(struct sprite *sprite, int *start_x, int *start_y, int *end_x, int *end_y)
Definition sprite.c:321
gui_dialog_add_content_widget
void gui_dialog_add_content_widget(struct gui_dialog *dlg, GtkWidget *wdg)
Definition gui_stuff.c:1095
gui_stuff.h
chatline.h
citydlg.h
gui_main.h
mapview.h
messagewin.h
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
map.h
meswin_popup_city
void meswin_popup_city(int message_index)
Definition messagewin_common.c:185
meswin_goto
void meswin_goto(int message_index)
Definition messagewin_common.c:213
meswin_get_num_messages
int meswin_get_num_messages(void)
Definition messagewin_common.c:167
meswin_get_message
const struct message * meswin_get_message(int message_index)
Definition messagewin_common.c:154
meswin_double_click
void meswin_double_click(int message_index)
Definition messagewin_common.c:225
meswin_set_visited_state
void meswin_set_visited_state(int message_index, bool state)
Definition messagewin_common.c:175
options.h
GUI_GTK_MSGCHAT_SPLIT
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:66
player.h
gui_dialog
Definition gui_stuff.h:69
message
Definition messagewin_common.h:29
message::descr
char * descr
Definition messagewin_common.h:30
message::visited
bool visited
Definition messagewin_common.h:36
message::event
enum event_type event
Definition messagewin_common.h:33
message::location_ok
bool location_ok
Definition messagewin_common.h:34
message::city_ok
bool city_ok
Definition messagewin_common.h:35
meswin_dialog
Definition messagewin.c:47
meswin_dialog::tree_view
GtkTreeView * tree_view
Definition messagewin.c:49
meswin_dialog::shell
struct gui_dialog * shell
Definition messagewin.c:48
sprite
Definition sprite.h:22
tileset
Definition tilespec.c:459
view
Definition mapview_common.h:36
widget
Definition widget.h:112
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
get_event_sprite
struct sprite * get_event_sprite(const struct tileset *t, enum event_type event)
Definition tilespec.c:6600