--- plrdlg.c.old Fri Jun 15 12:26:29 2001 +++ plrdlg.c Thu Jun 14 14:53:26 2001 @@ -25,6 +25,7 @@ #include "fcintl.h" #include "game.h" #include "packets.h" +#include "nation.h" #include "player.h" #include "support.h" @@ -35,6 +36,8 @@ #include "gui_stuff.h" #include "inteldlg.h" #include "spaceshipdlg.h" +#include "colors.h" +#include "graphics.h" #include "plrdlg.h" @@ -47,7 +50,11 @@ static GtkWidget *players_vision_command; static GtkWidget *players_sship_command; -static int list_index_to_player_index[MAX_NUM_PLAYERS]; +static int listindex_to_playerindex[MAX_NUM_PLAYERS]; +static int playerindex_to_listindex[MAX_NUM_PLAYERS]; +#define LI_2_PI(num) *(int*)(gtk_clist_get_row_data(GTK_CLIST(players_list), num)) + +static GdkPixmap *flags[MAX_NUM_PLAYERS]; static void create_players_dialog(void); static void players_button_callback(GtkWidget *w, gpointer data); @@ -59,7 +66,8 @@ static void players_list_ucallback(GtkWidget *w, gint row, gint column); static void players_sship_callback(GtkWidget *w, gpointer data); -#define NUM_COLOUMS 9 +#define NUM_COLUMS 11 +#define DEF_SORT_COLUMN 2 /* default sort column (1 = nation) */ static int delay_plrdlg_update=0; @@ -94,32 +102,64 @@ } +/* + * Sort plrs by column... + */ +static void sort_players_callback(GtkButton *button, gpointer *data) +{ + int sort_column = GPOINTER_TO_INT(data); + int i; + + /* first - sort the clist */ + if (sort_column == GTK_CLIST(players_list)->sort_column) { + if (GTK_CLIST(players_list)->sort_type == GTK_SORT_ASCENDING) { + gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_DESCENDING); + } else { + gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_ASCENDING); + } + } else { + gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_ASCENDING); + gtk_clist_set_sort_column(GTK_CLIST(players_list), sort_column); + } + gtk_clist_sort( GTK_CLIST(players_list)); + + /* second - update the index */ + for (i=0; irows; i++) { + playerindex_to_listindex[LI_2_PI(i)]=i; + } +} + + /**************************************************************** ... *****************************************************************/ void create_players_dialog(void) { - static gchar *titles_[NUM_COLOUMS] = { N_("Name"), N_("Nation"), N_("Embassy"), - N_("Dipl.State"), N_("Vision"), - N_("Reputation"), N_("State"), - N_("Host"), N_("Idle") }; + static gchar *titles_[NUM_COLUMS] = { N_("Name"), N_("Flag"), N_("Nation"), N_("Ai"), + N_("Embassy"), N_("Dipl.State"), N_("Vision"), N_("Reputation"), + N_("State"), N_("Host"), N_("Idle"), }; static gchar **titles; - int i; + int i; GtkAccelGroup *accel=gtk_accel_group_new(); - if (!titles) titles = intl_slist(NUM_COLOUMS, titles_); + /* initialises the indexes, necessary for update_players_dialog */ + for (i=0; ivbox), @@ -191,7 +231,154 @@ gtk_widget_add_accelerator(players_close_command, "clicked", accel, GDK_Escape, 0, 0); + /* default sort column is nation name */ + gtk_clist_set_sort_column(GTK_CLIST(players_list), DEF_SORT_COLUMN); + + /* all colums but flag column are clickable */ + for (i=0;i < NUM_COLUMS; i++) { + if (i!=1) { + gtk_signal_connect(GTK_OBJECT(GTK_CLIST(players_list)->column[i].button), + "clicked", GTK_SIGNAL_FUNC(sort_players_callback), GINT_TO_POINTER(i)); + } + } + + gtk_clist_clear(GTK_CLIST(players_list)); update_players_dialog(); + + /* dont resize the state column */ + gtk_clist_set_column_auto_resize (GTK_CLIST (players_list), 8, FALSE); +} + + +/* builds the text for the cells of a row in the player report. if update */ +/* is 1, only the changable entries are build. */ +void build_row(char **row, int i, int update) { + static char namebuf[32], flagbuf[1], aibuf[2], dsbuf[32], + repbuf[32], statebuf[32], idlebuf[32]; + const struct player_diplstate *pds; + + /* we cassume that neither name nor the nation of a player changes */ + if (update==0) { + /* the playername */ + my_snprintf(namebuf, sizeof(namebuf), "%-16s", game.players[i].name); + row[0] = namebuf; + + /* since flag is a pixmap, this can be empty */ + flagbuf[0]='\0'; + row[1] = flagbuf; + + /* the nation */ + row[2] = get_nation_name(game.players[i].nation); + } + + /* text for name, plus AI marker */ + aibuf[0]=(game.players[i].ai.control ? '*' :'\0'); + aibuf[1]='\0'; + + /* text for diplstate type and turns -- not applicable if this is me */ + if (i == game.player_idx) { + strcpy(dsbuf, "-"); + } else { + pds = player_get_diplstate(game.player_idx, i); + if (pds->type == DS_CEASEFIRE) { + my_snprintf(dsbuf, sizeof(dsbuf), "%s (%d)", + diplstate_text(pds->type), pds->turns_left); + } else { + my_snprintf(dsbuf, sizeof(dsbuf), "%s", + diplstate_text(pds->type)); + } + } + + /* text for state */ + if(game.players[i].is_alive) { + if(game.players[i].is_connected) { + if(game.players[i].turn_done) { + sz_strlcpy(statebuf, _("done")); + } else { + sz_strlcpy(statebuf, _("moving")); + } + } else { + statebuf[0]='\0'; + } + } else { + sz_strlcpy(statebuf, _("R.I.P")); + } + + /* text for idleness */ + if(game.players[i].nturns_idle>3) { + my_snprintf(idlebuf, sizeof(idlebuf), _("(idle %d turns)"), + game.players[i].nturns_idle-1); + } else { + idlebuf[0]='\0'; + } + + /* text for reputation */ + my_snprintf(repbuf, sizeof(repbuf), + reputation_text(game.players[i].reputation)); + + /* assemble the whole lot */ + row[3] = aibuf; + row[4] = get_embassy_status(game.player_ptr, &game.players[i]); + row[5] = dsbuf; + row[6] = get_vision_status(game.player_ptr, &game.players[i]); + row[7] = repbuf; + row[8] = statebuf; + row[9] = (char*)player_addr_hack(&game.players[i]); /* Fixme */ + row[10] = idlebuf; +} + + +/* builds the flag pixmap. since i am no gtk expert, this probably needs */ +/* to be looked at ... */ +void build_flag(int playerindex) { + int flag_h, flag_w, newflag_h, newflag_w, border; + GdkImage *flag_image, *mask_image; + GdkPixmap *flag_pixmap; + SPRITE *flag_sprite; + + flag_sprite=get_nation_by_plr(&game.players[playerindex])->flag_sprite; + + /* parsing the mask data for the flag dimensions. This solution is */ + /* indeed kinda hackish ... */ + flag_w=flag_sprite->width; + flag_h=flag_sprite->height; + + mask_image=gdk_image_get(flag_sprite->mask, 0, 0, flag_w, flag_h); + + + while (gdk_image_get_pixel(mask_image, flag_w-1, 0)==0 && flag_w>4) flag_w--; + if (flag_w<5) flag_w=flag_sprite->width; + + while (gdk_image_get_pixel(mask_image, 0, flag_h-1)==0 && flag_h>4) flag_h--; + if (flag_h<5) flag_h=flag_sprite->height; + gdk_image_destroy(mask_image); + + /* now scaling the original pixmap */ + newflag_h=GTK_CLIST(players_list)->row_height; + newflag_w=((double)newflag_h/flag_h)*flag_w; + + flag_pixmap=gtk_scale_pixmap(flag_sprite->pixmap, flag_w, flag_h, + newflag_w, newflag_h); + + /* drawing a black border ... can this be done more easily ? Do I */ + /* realy have to turn the gdk_pixmap into a gdk_image before doing */ + /* pixel operations ? */ + flag_image=gdk_image_get(flag_pixmap, 0, 0, newflag_w, newflag_h); + for (border=0; border3) { - my_snprintf(idlebuf, sizeof(idlebuf), _("(idle %d turns)"), - game.players[i].nturns_idle-1); - } else { - idlebuf[0]='\0'; - } - - /* text for state */ - if(game.players[i].is_alive) { - if(game.players[i].is_connected) { - if(game.players[i].turn_done) - sz_strlcpy(statebuf, _("done")); - else - sz_strlcpy(statebuf, _("moving")); - } - else - statebuf[0]='\0'; } - else - sz_strlcpy(statebuf, _("R.I.P")); - - /* text for name, plus AI marker */ - if(game.players[i].ai.control) - my_snprintf(namebuf, sizeof(namebuf), "*%-15s", game.players[i].name); - else - my_snprintf(namebuf, sizeof(namebuf), "%-16s", game.players[i].name); - - /* text for diplstate type and turns -- not applicable if this is me */ - if (i == game.player_idx) { - strcpy(dsbuf, "-"); + row=playerindex_to_listindex[i]; + if (row==-1) { + /* a nation is not in the player report yet. this happens when */ + /* the report is just opened and after a split. */ + build_row(row_texts, i, 0); + row=GTK_CLIST(players_list)->rows; + gtk_clist_append(GTK_CLIST(players_list), row_texts); + gtk_clist_set_row_data(GTK_CLIST(players_list), row, + &(listindex_to_playerindex[row])); + + build_flag(i); + gtk_clist_set_pixmap(GTK_CLIST(players_list),row, 1,flags[i],NULL); + + listindex_to_playerindex[row] = i; + playerindex_to_listindex[i] = row; + sort_needed=1; } else { - pds = player_get_diplstate(game.player_idx, i); - if (pds->type == DS_CEASEFIRE) { - my_snprintf(dsbuf, sizeof(dsbuf), "%s (%d)", - diplstate_text(pds->type), pds->turns_left); - } else { - my_snprintf(dsbuf, sizeof(dsbuf), "%s", - diplstate_text(pds->type)); + build_row(row_texts, i, 1); + /* the nation already had a row in the player report. in that case */ + /* we just update the row. */ + for(j=3; jtype) { + case DS_WAR: + state_col=colors_standard[COLOR_STD_RED]; + break; + case DS_ALLIANCE: + state_col=colors_standard[COLOR_STD_GROUND]; + break; + default: + state_col=colors_standard[COLOR_STD_BLACK]; + } + gtk_clist_set_foreground(GTK_CLIST(players_list), row, state_col); + } - list_index_to_player_index[j] = i; - j++; + if (sort_needed) { + /* when new nations appear in the report, we have to sort it */ + gtk_clist_sort(GTK_CLIST(players_list)); } - + gtk_clist_thaw(GTK_CLIST(players_list)); gtk_widget_show_all(players_list); } @@ -287,7 +453,7 @@ **************************************************************************/ void players_list_callback(GtkWidget *w, gint row, gint column) { - int player_index = list_index_to_player_index[row]; + int player_index = LI_2_PI(row); struct player *pplayer = &game.players[player_index]; if(pplayer->spaceship.state != SSHIP_NONE) @@ -349,7 +515,7 @@ return; row=(gint)selection->data; - player_index = list_index_to_player_index[row]; + player_index = LI_2_PI(row); if(player_has_embassy(game.player_ptr, &game.players[player_index])) { struct packet_diplomacy_info pa; @@ -379,7 +545,7 @@ struct packet_generic_integer pa; row = (gint)selection->data; - player_index = list_index_to_player_index[row]; + player_index = LI_2_PI(row); pa.value = player_index; send_packet_generic_integer(&aconnection, PACKET_PLAYER_CANCEL_PACT, @@ -402,7 +568,7 @@ struct packet_generic_integer pa; row = (gint)selection->data; - player_index = list_index_to_player_index[row]; + player_index = LI_2_PI(row); pa.value = player_index; send_packet_generic_integer(&aconnection, PACKET_PLAYER_REMOVE_VISION, @@ -423,7 +589,7 @@ return; row=(gint)selection->data; - player_index = list_index_to_player_index[row]; + player_index = LI_2_PI(row); if(player_has_embassy(game.player_ptr, &game.players[player_index])) popup_intel_dialog(&game.players[player_index]); @@ -442,7 +608,7 @@ return; row=(gint)selection->data; - player_index = list_index_to_player_index[row]; + player_index = LI_2_PI(row); popup_spaceship_dialog(&game.players[player_index]); }