Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2006:
[Freeciv-Dev] (PR#15688) gtk2 client needs pregame observer support
Home

[Freeciv-Dev] (PR#15688) gtk2 client needs pregame observer support

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#15688) gtk2 client needs pregame observer support
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 28 Feb 2006 23:21:12 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=15688 >

This patch implements the next step of pregame observer control. 
Right-clicking on a connection or menu brings up a useful little menu.

-jason

Index: client/gui-gtk-2.0/gui_main.c
===================================================================
--- client/gui-gtk-2.0/gui_main.c       (revision 11680)
+++ client/gui-gtk-2.0/gui_main.c       (working copy)
@@ -220,7 +220,6 @@
 static gboolean select_unit_pixmap_callback(GtkWidget *w, GdkEvent *ev, 
                                            gpointer data);
 static gint timer_callback(gpointer data);
-gboolean show_conn_popup(GtkWidget *view, GdkEventButton *ev, gpointer data);
 static gboolean quit_dialog_callback(void);
 
 
@@ -1401,6 +1400,7 @@
     gtk_tree_store_clear(conn_model);
     players_iterate(pplayer) {
       enum cmdlevel_id access_level = ALLOW_NONE;
+      int conn_id = -1;
 
       conn_list_iterate(pplayer->connections, pconn) {
         access_level = MAX(pconn->access_level, access_level);
@@ -1461,6 +1461,13 @@
        }
       }
 
+      conn_list_iterate(game.est_connections, pconn) {
+       if (pconn->player == pplayer && !pconn->observer) {
+         assert(conn_id == -1);
+         conn_id = pconn->id;
+       }
+      } conn_list_iterate_end;
+
       gtk_tree_store_append(conn_model, &it[pplayer->player_no], NULL);
       gtk_tree_store_set(conn_model, &it[pplayer->player_no],
                         0, pplayer->player_no,
@@ -1471,6 +1478,7 @@
                         5, team,
                         6, record_text,
                         7, rating_text,
+                        8, conn_id,
                         -1);
     } players_iterate_end;
     conn_list_iterate(game.est_connections, pconn) {
@@ -1494,74 +1502,13 @@
                         3, leader,
                         4, nation,
                         5, team,
+                        8, pconn->id,
                         -1);
     } conn_list_iterate_end;
   }
 }
 
 /**************************************************************************
- Show details about a user in the Connected Users dialog in a popup.
-**************************************************************************/
-gboolean show_conn_popup(GtkWidget *view, GdkEventButton *ev, gpointer data)
-{
-  GtkTreePath *path;
-  GtkTreeIter it;
-  GtkWidget *popup, *table, *label;
-  gchar *name;
-  struct connection *pconn;
-
-  /* Get the current selection in the Connected Users list */
-  if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(view),
-                                    ev->x, ev->y, &path, NULL, NULL, NULL)) {
-    return FALSE;
-  }
-
-  gtk_tree_model_get_iter(GTK_TREE_MODEL(conn_model), &it, path);
-  gtk_tree_path_free(path);
-
-  gtk_tree_model_get(GTK_TREE_MODEL(conn_model), &it, 1, &name, -1);
-  pconn = find_conn_by_user(name);
-
-  if (!pconn) {
-    return FALSE;
-  }
-
-  /* Show popup. */
-  popup = gtk_window_new(GTK_WINDOW_POPUP);
-  gtk_widget_set_app_paintable(popup, TRUE);
-  gtk_container_set_border_width(GTK_CONTAINER(popup), 4);
-  gtk_window_set_position(GTK_WINDOW(popup), GTK_WIN_POS_MOUSE);
-
-  table = gtk_table_new(2, 2, FALSE);
-  gtk_table_set_col_spacings(GTK_TABLE(table), 6);
-  gtk_container_add(GTK_CONTAINER(popup), table);
-
-  label = gtk_label_new(_("Name:"));
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
-  label = gtk_label_new(pconn->username);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-  gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 0, 1);
-
-  label = gtk_label_new(_("Host:"));
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
-  label = gtk_label_new(pconn->addr);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-  gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 1, 2);
-
-  gtk_widget_show_all(table);
-  gtk_widget_show(popup);
-
-  gdk_pointer_grab(popup->window, TRUE, GDK_BUTTON_RELEASE_MASK,
-                  NULL, NULL, ev->time);
-  gtk_grab_add(popup);
-  g_signal_connect_after(popup, "button_release_event",
-                        G_CALLBACK(show_info_button_release), NULL);
-  return FALSE;
-}
-
-/**************************************************************************
  obvious...
 **************************************************************************/
 void sound_bell(void)
Index: client/gui-gtk-2.0/gui_main.h
===================================================================
--- client/gui-gtk-2.0/gui_main.h       (revision 11680)
+++ client/gui-gtk-2.0/gui_main.h       (working copy)
@@ -76,7 +76,6 @@
 void enable_menus(bool enable);
 
 gboolean inputline_handler(GtkWidget *w, GdkEventKey *ev);
-gboolean show_conn_popup(GtkWidget *view, GdkEventButton *ev, gpointer data);
 
 void reset_unit_table(void);
 void popup_quit_dialog(void);
Index: client/gui-gtk-2.0/pages.c
===================================================================
--- client/gui-gtk-2.0/pages.c  (revision 11680)
+++ client/gui-gtk-2.0/pages.c  (working copy)
@@ -1009,61 +1009,181 @@
   send_new_aifill_to_server = old;
 }
 
-static struct player *team_menu_player;
+static struct player *conn_menu_player;
+static struct connection *conn_menu_conn;
 
 /****************************************************************************
-  Callback for when a team is chosen from the team menu.
+  Callback for when a team is chosen from the conn menu.
 ****************************************************************************/
-static void team_menu_entry_chosen(GtkMenuItem *menuitem, gpointer data)
+static void conn_menu_team_chosen(GtkMenuItem *menuitem, gpointer data)
 {
   struct team *pteam = data;
   char buf[1024];
 
-  if (pteam != team_menu_player->team) {
+  if (pteam != conn_menu_player->team) {
     my_snprintf(buf, sizeof(buf), "/team \"%s\" \"%s\"",
-               team_menu_player->name, team_get_name_orig(pteam));
+               conn_menu_player->name, team_get_name_orig(pteam));
     send_chat(buf);
   }
 }
 
 /****************************************************************************
-  Called when you click on a player's team; this function pops up a menu
+  Callback for when the "ready" entry is chosen from the conn menu.
+****************************************************************************/
+static void conn_menu_ready_chosen(GtkMenuItem *menuitem, gpointer data)
+{
+  struct player *pplayer = conn_menu_player;
+
+  dsend_packet_player_ready(&aconnection,
+                           pplayer->player_no, !pplayer->is_ready);
+}
+
+/****************************************************************************
+  Callback for when the pick-nation entry is chosen from the conn menu.
+****************************************************************************/
+static void conn_menu_nation_chosen(GtkMenuItem *menuitem, gpointer data)
+{
+  popup_races_dialog(conn_menu_player);
+}
+
+/****************************************************************************
+  Callback for when the "observe" entry is chosen from the conn menu.
+****************************************************************************/
+static void conn_menu_observe_chosen(GtkMenuItem *menuitem, gpointer data)
+{
+  char buf[1024];
+
+  my_snprintf(buf, sizeof(buf), "/observe \"%s\"",
+             conn_menu_player->name);
+  send_chat(buf);
+}
+
+/**************************************************************************
+ Show details about a user in the Connected Users dialog in a popup.
+**************************************************************************/
+static void show_conn_popup(struct player *pplayer, struct connection *pconn)
+{
+  GtkWidget *popup;
+  char buf[1024] = "";
+
+  cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
+              pconn ? pconn->username : pplayer->name);
+  cat_snprintf(buf, sizeof(buf), "\n");
+  if (pconn) {
+    cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
+  }
+  cat_snprintf(buf, sizeof(buf), "\n");
+
+  /* Show popup. */
+  popup = gtk_message_dialog_new(NULL, 0,
+                                GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, buf);
+  gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
+  setup_dialog(popup, toplevel);
+  g_signal_connect(popup, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+  gtk_window_present(GTK_WINDOW(popup));
+}
+
+/****************************************************************************
+  Callback for when the "info" entry is chosen from the conn menu.
+****************************************************************************/
+static void conn_menu_info_chosen(GtkMenuItem *menuitem, gpointer data)
+{
+  show_conn_popup(conn_menu_player, conn_menu_conn);
+}
+
+/****************************************************************************
+  Called when you click on a player; this function pops up a menu
   to allow changing the team.
 ****************************************************************************/
-static GtkWidget *create_team_menu(struct player *pplayer)
+static GtkWidget *create_conn_menu(struct player *pplayer,
+                                  struct connection *pconn)
 {
   GtkWidget *menu;
   GtkWidget *entry;
-  const int count = pplayer->team ? pplayer->team->players : 0;
-  bool need_empty_team = (count != 1);
-  int index;
+  char buf[128];
 
   menu = gtk_menu_new();
 
-  /* Can't use team_iterate here since it skips empty teams. */
-  for (index = 0; index < MAX_NUM_TEAMS; index++) {
-    struct team *pteam = team_get_by_id(index);
+  my_snprintf(buf, sizeof(buf), _("%s info"),
+             pconn ? pconn->username : pplayer->name);
+  entry = gtk_menu_item_new_with_label(buf);
+  g_object_set_data_full(G_OBJECT(menu),
+                        "info", entry,
+                        (GtkDestroyNotify) gtk_widget_unref);
+  gtk_container_add(GTK_CONTAINER(menu), entry);
+  g_signal_connect(GTK_OBJECT(entry), "activate",
+                  GTK_SIGNAL_FUNC(conn_menu_info_chosen), NULL);
 
-    if (pteam->players == 0) {
-      if (!need_empty_team) {
-       continue;
-      }
-      need_empty_team = FALSE;
-    }
+  entry = gtk_menu_item_new_with_label(_("Toggle player ready"));
+  gtk_widget_set_sensitive(entry, pplayer && !pplayer->ai.control);
+  g_object_set_data_full(G_OBJECT(menu),
+                        "ready", entry,
+                        (GtkDestroyNotify) gtk_widget_unref);
+  gtk_container_add(GTK_CONTAINER(menu), entry);
+  g_signal_connect(GTK_OBJECT(entry), "activate",
+                  GTK_SIGNAL_FUNC(conn_menu_ready_chosen), NULL);
 
-    entry = gtk_menu_item_new_with_label(team_get_name(pteam));
+  entry = gtk_menu_item_new_with_label(_("Pick nation"));
+  gtk_widget_set_sensitive(entry,
+                          pplayer
+                          && can_conn_edit_players_nation(&aconnection,
+                                                          pplayer));
+  g_object_set_data_full(G_OBJECT(menu),
+                        "nation", entry,
+                        (GtkDestroyNotify) gtk_widget_unref);
+  gtk_container_add(GTK_CONTAINER(menu), entry);
+  g_signal_connect(GTK_OBJECT(entry), "activate",
+                  GTK_SIGNAL_FUNC(conn_menu_nation_chosen), NULL);
+
+  entry = gtk_menu_item_new_with_label(_("Observe this player"));
+  g_object_set_data_full(G_OBJECT(menu),
+                        "observe", entry,
+                        (GtkDestroyNotify) gtk_widget_unref);
+  gtk_container_add(GTK_CONTAINER(menu), entry);
+  g_signal_connect(GTK_OBJECT(entry), "activate",
+                  GTK_SIGNAL_FUNC(conn_menu_observe_chosen), NULL);
+
+  if (pplayer && game.info.is_new_game) {
+    const int count = pplayer->team ? pplayer->team->players : 0;
+    bool need_empty_team = (count != 1);
+    int index;
+
+    entry = gtk_separator_menu_item_new();
     g_object_set_data_full(G_OBJECT(menu),
-                          team_get_name_orig(pteam), entry,
+                          "sep1", entry,
                           (GtkDestroyNotify) gtk_widget_unref);
-    gtk_widget_show(entry);
     gtk_container_add(GTK_CONTAINER(menu), entry);
-    g_signal_connect(GTK_OBJECT(entry), "activate",
-                    GTK_SIGNAL_FUNC(team_menu_entry_chosen),
-                    pteam);
+
+    /* Can't use team_iterate here since it skips empty teams. */
+    for (index = 0; index < MAX_NUM_TEAMS; index++) {
+      struct team *pteam = team_get_by_id(index);
+      char text[128];
+
+      if (pteam->players == 0) {
+       if (!need_empty_team) {
+         continue;
+       }
+       need_empty_team = FALSE;
+      }
+
+      /* TRANS: e.g., "Put on Team 5" */
+      my_snprintf(text, sizeof(text), _("Put on %s"), team_get_name(pteam));
+      entry = gtk_menu_item_new_with_label(text);
+      g_object_set_data_full(G_OBJECT(menu),
+                            team_get_name_orig(pteam), entry,
+                            (GtkDestroyNotify) gtk_widget_unref);
+      gtk_container_add(GTK_CONTAINER(menu), entry);
+      g_signal_connect(GTK_OBJECT(entry), "activate",
+                      GTK_SIGNAL_FUNC(conn_menu_team_chosen),
+                      pteam);
+    }
   }
 
-  team_menu_player = pplayer;
+  conn_menu_player = pplayer;
+  conn_menu_conn = pconn;
 
+  gtk_widget_show_all(menu);
+
   return menu;
 }
 
@@ -1078,10 +1198,12 @@
   GtkTreeIter iter;
   GtkTreePath *path = NULL;
   GtkTreeViewColumn *column = NULL;
-  int player_no;
+  int player_no, conn_id;
   struct player *pplayer;
+  struct connection *pconn;
 
   if (event->type != GDK_BUTTON_PRESS
+      || event->button != 3
       || !gtk_tree_view_get_path_at_pos(tree,
                                        event->x, event->y,
                                        &path, &column, NULL, NULL)) {
@@ -1092,36 +1214,16 @@
   gtk_tree_path_free(path);
   gtk_tree_model_get(model, &iter, 0, &player_no, -1);
   pplayer = get_player(player_no);
+  gtk_tree_model_get(model, &iter, 8, &conn_id, -1);
+  pconn = find_conn_by_id(conn_id);
 
-  if (column == nation_col) {
-    if (!pplayer || !can_conn_edit_players_nation(&aconnection, pplayer)) {
-      return FALSE;
-    }
-
-    popup_races_dialog(pplayer);
-    return TRUE;
-  } else if (column == ready_col) {
-    gboolean is_ready;
-
-    if (!pplayer) {
-      return FALSE;
-    }
-
-    gtk_tree_model_get(model, &iter, 2, &is_ready, -1);
-    dsend_packet_player_ready(&aconnection, pplayer->player_no, !is_ready);
-    return TRUE;
-  } else if (column == team_col) {
-    if (pplayer && game.info.is_new_game) {
-      GtkWidget *menu = create_team_menu(pplayer);
-
-      gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
-                    event->button, 0);
-      return TRUE;
-    }
-    return FALSE;
-  } else {
-    return show_conn_popup(widget, event, data);
-  }
+  gtk_menu_popup(GTK_MENU(create_conn_menu(pplayer, pconn)),
+                NULL, NULL, NULL, NULL,
+                event->button, 0);
+  return TRUE;
+#if 0
+  return show_conn_popup(widget, event, data);
+#endif
 }
 
 /**************************************************************************
@@ -1223,11 +1325,12 @@
   gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, FALSE, 8);
 
 
-  conn_model = gtk_tree_store_new(8, G_TYPE_INT,
+  conn_model = gtk_tree_store_new(9, G_TYPE_INT,
                                  G_TYPE_STRING, G_TYPE_BOOLEAN,
                                  G_TYPE_STRING, G_TYPE_STRING,
                                  G_TYPE_STRING, G_TYPE_STRING,
-                                 G_TYPE_STRING);
+                                 G_TYPE_STRING,
+                                 G_TYPE_INT);
 
   view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(conn_model));
   g_object_unref(conn_model);

[Prev in Thread] Current Thread [Next in Thread]