diff -Nur -Xdiff_ignore ../../cvs/freeciv/client/gui-gtk/mapctrl.c ./client/gui-gtk/mapctrl.c --- ../../cvs/freeciv/client/gui-gtk/mapctrl.c Fri Jun 14 09:31:29 2002 +++ ./client/gui-gtk/mapctrl.c Fri Jul 12 12:21:26 2002 @@ -60,16 +60,17 @@ } /************************************************************************** -... + Popup a label with information about the tile, unit, city, when the user + used the middle mouse button on the map. **************************************************************************/ static void popit(GdkEventButton *event, int xtile, int ytile) { GtkWidget *p, *b; static struct map_position cross_list[2 + 1]; struct map_position *cross_head = cross_list; - int i, count = 0; - int popx, popy; + int i; char s[512]; + static struct tmousepos mousepos; struct city *pcity; struct unit *punit; struct tile *ptile = map_get_tile(xtile, ytile); @@ -83,26 +84,22 @@ my_snprintf(s, sizeof(s), _("Location: (%d, %d)"), xtile, ytile); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; #endif /* DEBUG */ my_snprintf(s, sizeof(s), _("Terrain: %s"), map_get_tile_info_text(xtile, ytile)); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; my_snprintf(s, sizeof(s), _("Food/Prod/Trade: %s"), map_get_tile_fpt_text(xtile, ytile)); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; if (tile_has_special(ptile, S_HUT)) { gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", _("Minor Tribe Village"), NULL); - count++; } if((pcity = map_get_city(xtile, ytile))) { @@ -110,12 +107,10 @@ get_nation_name(city_owner(pcity)->nation)); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; if (city_got_citywalls(pcity)) { gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", _("with City Walls"), NULL); - count++; } } @@ -124,14 +119,12 @@ sz_strlcat(s, map_get_infrastructure_text(ptile->special)); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; } sz_strlcpy(s, _("Activity: ")); if (concat_tile_activity_text(s, sizeof(s), xtile, ytile)) { gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; } if((punit = find_visible_unit(ptile)) && !pcity) { @@ -148,7 +141,6 @@ get_nation_name(unit_owner(punit)->nation), cn); gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; if(punit->owner == game.player_idx) { char uc[64] = ""; @@ -174,7 +166,6 @@ } gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, "GtkLabel::label", s, NULL); - count++; } cross_head->x = xtile; @@ -191,12 +182,13 @@ GTK_SIGNAL_FUNC(popupinfo_popdown_callback), cross_list); - /* displace popup so as not to obscure it by the mouse cursor */ - popx = event->x_root + 16; - popy = event->y_root - (8 * count); - if (popy < 0) - popy = 0; - gtk_widget_popup(p, popx, popy); + mousepos.x = event->x_root; + mousepos.y = event->y_root; + gtk_signal_connect(GTK_OBJECT(p), "size-allocate", + GTK_SIGNAL_FUNC(popupinfo_positioning_callback), + &mousepos); + + gtk_widget_show(p); gdk_pointer_grab(p->window, TRUE, GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); gtk_grab_add(p); @@ -216,6 +208,39 @@ while (cross_list->x >= 0) { refresh_tile_mapcanvas(cross_list->x, cross_list->y, TRUE); cross_list++; + } +} + +/************************************************************************** + Put the popup on a smart position, after the real size of the widget is + known: left of the cursor if within the right half of the map, and vice + versa; displace the popup so as not to obscure it by the mouse cursor; + stay always within the map and the screen. +**************************************************************************/ +void popupinfo_positioning_callback(GtkWidget *w, GtkAllocation *alloc, + gpointer data) +{ + struct tmousepos *mousepos = (struct tmousepos *)data; + gint x, y, width, height; + gint minx, miny, maxx, maxy; + + gdk_window_get_origin(map_canvas->window, &x, &y); + gdk_window_get_size(map_canvas->window, &width, &height); + minx = MAX(x, 0); + miny = MAX(y, 0); + maxx = MIN(x + width, gdk_screen_width()) - alloc->width; + maxy = MIN(y + height, gdk_screen_height()) - alloc->height; + if ((width / 2 + x) > mousepos->x) { + /* left part of the map */ + gtk_widget_set_uposition(w, MAX(MIN(mousepos->x + 16, maxx), minx), + MAX(MIN(mousepos->y - (alloc->height / 2), maxy), + miny)); + } else { + /* right part of the map */ + gtk_widget_set_uposition(w, MAX(MIN(mousepos->x - alloc->width - 16, + maxx), minx), + MAX(MIN(mousepos->y - (alloc->height / 2), maxy), + miny)); } } diff -Nur -Xdiff_ignore ../../cvs/freeciv/client/gui-gtk/mapctrl.h ./client/gui-gtk/mapctrl.h --- ../../cvs/freeciv/client/gui-gtk/mapctrl.h Thu Feb 7 19:21:10 2002 +++ ./client/gui-gtk/mapctrl.h Fri Jul 12 12:16:27 2002 @@ -18,6 +18,7 @@ #include "mapctrl_g.h" struct unit; +struct tmousepos {int x, y;}; void key_city_workers(GtkWidget *w, GdkEventKey *ev); void adjust_workers(GtkWidget *widget, GdkEventButton *ev); @@ -31,6 +32,8 @@ void center_on_unit(void); void focus_to_next_unit(void); void popupinfo_popdown_callback(GtkWidget *w, gpointer data); +void popupinfo_positioning_callback(GtkWidget *w, GtkAllocation *alloc, + gpointer user_data); /* Color to use to display the workers */ extern int city_workers_color;