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-3.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
49 GtkTreeView *tree_view;
50};
51
52/* Those values must match meswin_dialog_store_new(). */
64
69
70static struct meswin_dialog meswin = { NULL, };
71
72/************************************************************************/
75static 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/************************************************************************/
88static 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/************************************************************************/
102static 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/************************************************************************/
119static 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);
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,
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/************************************************************************/
196static 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
213 NULL != pmsg && pmsg->location_ok);
215 NULL != pmsg && pmsg->city_ok);
216}
217
218/************************************************************************/
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)) {
238 meswin_dialog_set_visited(model, &iter, TRUE);
239 }
240}
241
242/************************************************************************/
248 GdkEventButton *ev,
249 gpointer data)
250{
251 GtkTreePath *path = NULL;
252 GtkTreeModel *model;
253 GtkTreeIter iter;
254 gint row;
255
256 fc_assert_ret_val(GTK_IS_TREE_VIEW(widget), FALSE);
257
258 if (GDK_BUTTON_PRESS != ev->type || 3 != ev->button) {
259 return FALSE;
260 }
261
262 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), ev->x, ev->y,
263 &path, NULL, NULL, NULL)) {
264 return TRUE;
265 }
266
267 model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
268 if (gtk_tree_model_get_iter(model, &iter, path)) {
269 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
270 meswin_goto(row);
271 }
272 gtk_tree_path_free(path);
273
274 return TRUE;
275}
276
277/************************************************************************/
280static void meswin_dialog_response_callback(struct gui_dialog *pgui_dialog,
281 int response, gpointer data)
282{
283 struct meswin_dialog *pdialog = data;
284 GtkTreeSelection *selection;
285 GtkTreeModel *model;
286 GtkTreeIter iter;
287 gint row;
288
289 switch (response) {
290 case MESWIN_RES_GOTO:
292 break;
293 default:
294 gui_dialog_destroy(pgui_dialog);
295 return;
296 }
297
298 selection = gtk_tree_view_get_selection(pdialog->tree_view);
299 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
300 return;
301 }
302
303 gtk_tree_model_get(model, &iter, MESWIN_COL_ID, &row, -1);
304
305 switch (response) {
306 case MESWIN_RES_GOTO:
307 meswin_goto(row);
308 break;
311 break;
312 }
313 meswin_dialog_set_visited(model, &iter, TRUE);
314}
315
316/************************************************************************/
319static void meswin_dialog_init(struct meswin_dialog *pdialog)
320{
321 GtkWidget *view, *sw, *cmd, *notebook;
322 GtkContainer *vbox;
323 GtkListStore *store;
324 GtkTreeSelection *selection;
325 GtkCellRenderer *renderer;
326 GtkTreeViewColumn *col;
327
328 fc_assert_ret(NULL != pdialog);
329
330 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
331 notebook = right_notebook;
332 } else {
333 notebook = bottom_notebook;
334 }
335
336 gui_dialog_new(&pdialog->shell, GTK_NOTEBOOK(notebook), pdialog, TRUE);
337 gui_dialog_set_title(pdialog->shell, _("Messages"));
338 vbox = GTK_CONTAINER(pdialog->shell->vbox);
339
340 sw = gtk_scrolled_window_new(NULL, NULL);
341 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
342 GTK_SHADOW_ETCHED_IN);
343 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
344 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
345 gtk_container_add(vbox, sw);
346
347 store = meswin_dialog_store_new();
348 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
349 gtk_widget_set_hexpand(view, TRUE);
350 gtk_widget_set_vexpand(view, TRUE);
351 g_object_unref(store);
352 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(view));
353 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
354 g_signal_connect(view, "row_activated",
355 G_CALLBACK(meswin_dialog_row_activated_callback), NULL);
356 g_signal_connect(view, "button-press-event",
357 G_CALLBACK(meswin_dialog_button_press_callback), NULL);
358 pdialog->tree_view = GTK_TREE_VIEW(view);
359
360 renderer = gtk_cell_renderer_pixbuf_new();
361 col = gtk_tree_view_column_new_with_attributes(NULL, renderer,
362 "pixbuf", MESWIN_COL_ICON, NULL);
363 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
364 gtk_tree_view_column_set_visible(col, !GUI_GTK_OPTION(small_display_layout));
365
366 renderer = gtk_cell_renderer_text_new();
367 col = gtk_tree_view_column_new_with_attributes(NULL, renderer,
368 "text", MESWIN_COL_MESSAGE,
369 "weight", MESWIN_COL_WEIGHT,
370 "style", MESWIN_COL_STYLE,
371 NULL);
372 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
373 gtk_container_add(GTK_CONTAINER(sw), view);
374
375 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
376 g_signal_connect(selection, "changed",
377 G_CALLBACK(meswin_dialog_selection_callback), pdialog);
378
379 gui_dialog_add_button(pdialog->shell, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
380
381 if (GUI_GTK_OPTION(show_message_window_buttons)) {
382 cmd = gui_dialog_add_stockbutton(pdialog->shell, GTK_STOCK_ZOOM_IN,
383 _("I_nspect City"),
385 gtk_widget_set_sensitive(cmd, FALSE);
386
387 cmd = gui_dialog_add_stockbutton(pdialog->shell, GTK_STOCK_JUMP_TO,
388 _("Goto _Location"), MESWIN_RES_GOTO);
389 gtk_widget_set_sensitive(cmd, FALSE);
390 }
391
394 gui_dialog_set_default_size(pdialog->shell, 520, 300);
395
396 meswin_dialog_refresh(pdialog);
397 gui_dialog_show_all(pdialog->shell);
398}
399
400/************************************************************************/
403static void meswin_dialog_free(struct meswin_dialog *pdialog)
404{
405 fc_assert_ret(NULL != pdialog);
406
407 gui_dialog_destroy(pdialog->shell);
408 fc_assert(NULL == pdialog->shell);
409
410 memset(pdialog, 0, sizeof(*pdialog));
411}
412
413/************************************************************************/
416void meswin_dialog_popup(bool raise)
417{
418 if (NULL == meswin.shell) {
420 }
421
423 if (raise) {
425 }
426}
427
428/************************************************************************/
432{
433 if (NULL != meswin.shell) {
435 fc_assert(NULL == meswin.shell);
436 }
437}
438
439/************************************************************************/
443{
444 return (NULL != meswin.shell);
445}
446
447/************************************************************************/
451{
452 if (NULL != meswin.shell) {
454 }
455}
#define _(String)
Definition fcintl.h:67
GtkWidget * bottom_notebook
Definition gui_main.c:128
GtkWidget * right_notebook
Definition gui_main.c:128
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
void gui_dialog_destroy(struct gui_dialog *dlg)
Definition gui_stuff.c:951
void gui_dialog_present(struct gui_dialog *dlg)
Definition gui_stuff.c:834
void gui_dialog_raise(struct gui_dialog *dlg)
Definition gui_stuff.c:864
void gui_dialog_new(struct gui_dialog **pdlg, GtkNotebook *notebook, gpointer user_data, bool check_top)
Definition gui_stuff.c:504
void gui_dialog_response_set_callback(struct gui_dialog *dlg, GUI_DIALOG_RESPONSE_FUN fun)
Definition gui_stuff.c:985
GtkWidget * gui_dialog_add_button(struct gui_dialog *dlg, const char *text, int response)
Definition gui_stuff.c:706
GtkWidget * gui_dialog_add_stockbutton(struct gui_dialog *dlg, const char *stock, const char *text, int response)
Definition gui_stuff.c:690
void gui_dialog_show_all(struct gui_dialog *dlg)
Definition gui_stuff.c:794
void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
Definition gui_stuff.c:932
void gui_dialog_set_default_size(struct gui_dialog *dlg, int width, int height)
Definition gui_stuff.c:916
void gui_dialog_alert(struct gui_dialog *dlg)
Definition gui_stuff.c:887
void gui_dialog_set_response_sensitive(struct gui_dialog *dlg, int response, bool setting)
Definition gui_stuff.c:759
static void meswin_dialog_init(struct meswin_dialog *pdialog)
Definition messagewin.c:319
static gboolean meswin_dialog_button_press_callback(GtkWidget *widget, GdkEventButton *ev, gpointer data)
Definition messagewin.c:247
void meswin_dialog_popdown(void)
Definition messagewin.c:431
static void meswin_dialog_visited_get_attr(bool visited, gint *weight, gint *style)
Definition messagewin.c:88
static void meswin_dialog_row_activated_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition messagewin.c:221
static void meswin_dialog_set_visited(GtkTreeModel *model, GtkTreeIter *iter, bool visited)
Definition messagewin.c:102
static struct meswin_dialog meswin
Definition messagewin.c:70
static GtkListStore * meswin_dialog_store_new(void)
Definition messagewin.c:75
static void meswin_dialog_response_callback(struct gui_dialog *pgui_dialog, int response, gpointer data)
Definition messagewin.c:280
void meswin_dialog_popup(bool raise)
Definition messagewin.c:416
static void meswin_dialog_refresh(struct meswin_dialog *pdialog)
Definition messagewin.c:119
meswin_columns
Definition messagewin.c:53
@ MESWIN_COL_NUM
Definition messagewin.c:62
@ MESWIN_COL_MESSAGE
Definition messagewin.c:55
@ MESWIN_COL_STYLE
Definition messagewin.c:59
@ MESWIN_COL_ID
Definition messagewin.c:60
@ MESWIN_COL_ICON
Definition messagewin.c:54
@ MESWIN_COL_WEIGHT
Definition messagewin.c:58
meswin_responses
Definition messagewin.c:65
@ MESWIN_RES_GOTO
Definition messagewin.c:66
@ MESWIN_RES_POPUP_CITY
Definition messagewin.c:67
static void meswin_dialog_free(struct meswin_dialog *pdialog)
Definition messagewin.c:403
static void meswin_dialog_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition messagewin.c:196
void real_meswin_dialog_update(void *unused)
Definition messagewin.c:450
bool meswin_dialog_is_open(void)
Definition messagewin.c:442
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
void sprite_get_bounding_box(struct sprite *sprite, int *start_x, int *start_y, int *end_x, int *end_y)
Definition sprite.c:321
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
void meswin_popup_city(int message_index)
void meswin_goto(int message_index)
int meswin_get_num_messages(void)
const struct message * meswin_get_message(int message_index)
void meswin_double_click(int message_index)
void meswin_set_visited_state(int message_index, bool state)
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:66
GtkWidget * vbox
Definition gui_stuff.h:71
enum event_type event
GtkTreeView * tree_view
Definition messagewin.c:49
struct gui_dialog * shell
Definition messagewin.c:48
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct sprite * get_event_sprite(const struct tileset *t, enum event_type event)
Definition tilespec.c:6596