1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
15 #include <fc_config.h>
37 /* client/gui-gtk-2.0 */
41 #include "gui_stuff.h"
44 #include "messagewin.h"
47 struct meswin_dialog
{
48 struct gui_dialog
*shell
;
49 GtkTreeView
*tree_view
;
52 /* Those values must match meswin_dialog_store_new(). */
65 enum meswin_responses
{
70 static struct meswin_dialog meswin
= { NULL
, };
72 /****************************************************************************
73 Create a tree model for the message window.
74 ****************************************************************************/
75 static GtkListStore
*meswin_dialog_store_new(void)
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 */
85 /****************************************************************************
86 Get the pango attributes for the visited state.
87 ****************************************************************************/
88 static void meswin_dialog_visited_get_attr(bool visited
, gint
*weight
,
92 *weight
= (visited
? PANGO_WEIGHT_NORMAL
: PANGO_WEIGHT_BOLD
);
95 *style
= (visited
? PANGO_STYLE_ITALIC
: PANGO_STYLE_NORMAL
);
99 /****************************************************************************
100 Set the visited state of the store.
101 ****************************************************************************/
102 static void meswin_dialog_set_visited(GtkTreeModel
*model
,
103 GtkTreeIter
*iter
, bool visited
)
105 gint row
, weight
, style
;
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
,
113 meswin_set_visited_state(row
, visited
);
116 /****************************************************************************
117 Refresh a message window dialog.
118 ****************************************************************************/
119 static void meswin_dialog_refresh(struct meswin_dialog
*pdialog
)
121 GtkTreeSelection
*selection
;
125 const struct message
*pmsg
;
127 int selected
, i
, num
;
128 bool need_alert
= FALSE
;
130 fc_assert_ret(NULL
!= pdialog
);
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);
140 model
= gtk_tree_view_get_model(pdialog
->tree_view
);
141 store
= GTK_LIST_STORE(model
);
142 num
= meswin_get_num_messages();
144 gtk_list_store_clear(store
);
145 for (i
= 0; i
< num
; i
++) {
148 int x0
, y0
, x1
, y1
, w
, h
;
150 pmsg
= meswin_get_message(i
);
152 if (gui_options
.gui_gtk2_new_messages_go_to_top
) {
153 gtk_list_store_prepend(store
, &iter
);
155 gtk_list_store_append(store
, &iter
);
158 icon
= get_event_sprite(tileset
, pmsg
->event
);
159 sprite_get_bounding_box(icon
, &x0
, &y0
, &x1
, &y1
);
162 pb
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, w
, h
);
163 gdk_pixbuf_copy_area(sprite_get_pixbuf(icon
), x0
, y0
, w
, h
,
166 meswin_dialog_visited_get_attr(pmsg
->visited
, &weight
, &style
);
167 gtk_list_store_set(store
, &iter
,
169 MESWIN_COL_MESSAGE
, pmsg
->descr
,
170 MESWIN_COL_WEIGHT
, weight
,
171 MESWIN_COL_STYLE
, style
,
176 /* Restore the selection. */
177 gtk_tree_selection_select_iter(selection
, &iter
);
180 if (!pmsg
->visited
) {
186 gui_dialog_alert(pdialog
->shell
);
190 /**************************************************************************
191 Selection changed callback.
192 **************************************************************************/
193 static void meswin_dialog_selection_callback(GtkTreeSelection
*selection
,
196 struct meswin_dialog
*pdialog
= data
;
197 const struct message
*pmsg
;
202 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
206 gtk_tree_model_get(model
, &iter
, MESWIN_COL_ID
, &row
, -1);
207 pmsg
= meswin_get_message(row
);
209 gui_dialog_set_response_sensitive(pdialog
->shell
, MESWIN_RES_GOTO
,
210 NULL
!= pmsg
&& pmsg
->location_ok
);
211 gui_dialog_set_response_sensitive(pdialog
->shell
, MESWIN_RES_POPUP_CITY
,
212 NULL
!= pmsg
&& pmsg
->city_ok
);
215 /**************************************************************************
216 A row has been activated by the user.
217 **************************************************************************/
218 static void meswin_dialog_row_activated_callback(GtkTreeView
*view
,
220 GtkTreeViewColumn
*col
,
223 GtkTreeModel
*model
= gtk_tree_view_get_model(view
);
227 if (!gtk_tree_model_get_iter(model
, &iter
, path
)) {
231 gtk_tree_model_get(model
, &iter
, MESWIN_COL_ID
, &row
, -1);
233 if (NULL
!= meswin_get_message(row
)) {
234 meswin_double_click(row
);
235 meswin_dialog_set_visited(model
, &iter
, TRUE
);
239 /****************************************************************************
240 Mouse button press handler for the message window treeview. We only
241 care about right clicks on a row; this action centers on the tile
242 associated with the event at that row (if applicable).
243 ****************************************************************************/
244 static gboolean
meswin_dialog_button_press_callback(GtkWidget
*widget
,
248 GtkTreePath
*path
= NULL
;
253 fc_assert_ret_val(GTK_IS_TREE_VIEW(widget
), FALSE
);
255 if (GDK_BUTTON_PRESS
!= ev
->type
|| 3 != ev
->button
) {
259 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget
), ev
->x
, ev
->y
,
260 &path
, NULL
, NULL
, NULL
)) {
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);
269 gtk_tree_path_free(path
);
274 /**************************************************************************
275 Dialog response callback.
276 **************************************************************************/
277 static void meswin_dialog_response_callback(struct gui_dialog
*pgui_dialog
,
278 int response
, gpointer data
)
280 struct meswin_dialog
*pdialog
= data
;
281 GtkTreeSelection
*selection
;
287 case MESWIN_RES_GOTO
:
288 case MESWIN_RES_POPUP_CITY
:
291 gui_dialog_destroy(pgui_dialog
);
295 selection
= gtk_tree_view_get_selection(pdialog
->tree_view
);
296 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
300 gtk_tree_model_get(model
, &iter
, MESWIN_COL_ID
, &row
, -1);
303 case MESWIN_RES_GOTO
:
306 case MESWIN_RES_POPUP_CITY
:
307 meswin_popup_city(row
);
310 meswin_dialog_set_visited(model
, &iter
, TRUE
);
313 /****************************************************************************
314 Initilialize a message window dialog.
315 ****************************************************************************/
316 static void meswin_dialog_init(struct meswin_dialog
*pdialog
)
318 GtkWidget
*view
, *sw
, *cmd
, *notebook
;
321 GtkTreeSelection
*selection
;
322 GtkCellRenderer
*renderer
;
323 GtkTreeViewColumn
*col
;
325 fc_assert_ret(NULL
!= pdialog
);
327 if (gui_options
.gui_gtk2_message_chat_location
== GUI_GTK_MSGCHAT_SPLIT
) {
328 notebook
= right_notebook
;
330 notebook
= bottom_notebook
;
333 gui_dialog_new(&pdialog
->shell
, GTK_NOTEBOOK(notebook
), pdialog
, TRUE
);
334 gui_dialog_set_title(pdialog
->shell
, _("Messages"));
335 vbox
= GTK_BOX(pdialog
->shell
->vbox
);
337 sw
= gtk_scrolled_window_new(NULL
, NULL
);
338 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw
),
339 GTK_SHADOW_ETCHED_IN
);
340 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
),
341 GTK_POLICY_AUTOMATIC
, GTK_POLICY_ALWAYS
);
342 gtk_box_pack_start(vbox
, sw
, TRUE
, TRUE
, 0);
344 store
= meswin_dialog_store_new();
345 view
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
346 g_object_unref(store
);
347 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(view
));
348 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view
), FALSE
);
349 g_signal_connect(view
, "row_activated",
350 G_CALLBACK(meswin_dialog_row_activated_callback
), NULL
);
351 g_signal_connect(view
, "button-press-event",
352 G_CALLBACK(meswin_dialog_button_press_callback
), NULL
);
353 pdialog
->tree_view
= GTK_TREE_VIEW(view
);
355 renderer
= gtk_cell_renderer_pixbuf_new();
356 col
= gtk_tree_view_column_new_with_attributes(NULL
, renderer
,
357 "pixbuf", MESWIN_COL_ICON
, NULL
);
358 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), col
);
359 gtk_tree_view_column_set_visible(col
, !gui_options
.gui_gtk2_small_display_layout
);
361 renderer
= gtk_cell_renderer_text_new();
362 col
= gtk_tree_view_column_new_with_attributes(NULL
, renderer
,
363 "text", MESWIN_COL_MESSAGE
,
364 "weight", MESWIN_COL_WEIGHT
,
365 "style", MESWIN_COL_STYLE
,
367 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), col
);
368 gtk_container_add(GTK_CONTAINER(sw
), view
);
370 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(view
));
371 g_signal_connect(selection
, "changed",
372 G_CALLBACK(meswin_dialog_selection_callback
), pdialog
);
374 if (gui_options
.gui_gtk2_show_message_window_buttons
) {
375 cmd
= gui_dialog_add_stockbutton(pdialog
->shell
, GTK_STOCK_JUMP_TO
,
376 _("Goto _Location"), MESWIN_RES_GOTO
);
377 gtk_widget_set_sensitive(cmd
, FALSE
);
379 cmd
= gui_dialog_add_stockbutton(pdialog
->shell
, GTK_STOCK_ZOOM_IN
,
381 MESWIN_RES_POPUP_CITY
);
382 gtk_widget_set_sensitive(cmd
, FALSE
);
385 gui_dialog_add_button(pdialog
->shell
, GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
);
386 gui_dialog_response_set_callback(pdialog
->shell
,
387 meswin_dialog_response_callback
);
388 gui_dialog_set_default_size(pdialog
->shell
, 520, 300);
390 meswin_dialog_refresh(pdialog
);
391 gui_dialog_show_all(pdialog
->shell
);
394 /****************************************************************************
395 Closes a message window dialog.
396 ****************************************************************************/
397 static void meswin_dialog_free(struct meswin_dialog
*pdialog
)
399 fc_assert_ret(NULL
!= pdialog
);
401 gui_dialog_destroy(pdialog
->shell
);
402 fc_assert(NULL
== pdialog
->shell
);
404 memset(pdialog
, 0, sizeof(*pdialog
));
407 /****************************************************************************
408 Popup the dialog inside the main-window, and optionally raise it.
409 ****************************************************************************/
410 void meswin_dialog_popup(bool raise
)
412 if (NULL
== meswin
.shell
) {
413 meswin_dialog_init(&meswin
);
416 gui_dialog_present(meswin
.shell
);
418 gui_dialog_raise(meswin
.shell
);
422 /****************************************************************************
423 Closes the message window dialog.
424 ****************************************************************************/
425 void meswin_dialog_popdown(void)
427 if (NULL
!= meswin
.shell
) {
428 meswin_dialog_free(&meswin
);
429 fc_assert(NULL
== meswin
.shell
);
433 /****************************************************************************
434 Return TRUE iff the message window is open.
435 ****************************************************************************/
436 bool meswin_dialog_is_open(void)
438 return (NULL
!= meswin
.shell
);
441 /****************************************************************************
442 Update the message window dialog.
443 ****************************************************************************/
444 void real_meswin_dialog_update(void)
446 if (NULL
!= meswin
.shell
) {
447 meswin_dialog_refresh(&meswin
);