Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2006:
[Freeciv-Dev] (PR#15636) Editor: Change city from within city dialog
Home

[Freeciv-Dev] (PR#15636) Editor: Change city from within city dialog

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#15636) Editor: Change city from within city dialog
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Sun, 19 Feb 2006 16:36:00 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Currently in the editor we change the city by painting over it. I consider
this bad and unintuitive. Instead, clicking on the city in edit mode
should allow us to edit it from the city dialog. This patch adds this
feature.

Click a city in edit mode to open it. You now have two new buttons that
allows you to add or remove citizens. You can sell or buy any number of
units and buildings that are added instantly, and without changing gold
reserves. Buying units from within the city dialog makes the units have
this city as their home city, just as you would expect, and unlike the
unit tool.

The citizen buttons are bit fickle, and it is easy to push them too many
times, quickly allowing you to ruin a city, for example. Fixing this
somehow is way beyond my puny gtk skills.

  - Per

PNG image

Index: server/cityhand.c
===================================================================
--- server/cityhand.c   (revision 11621)
+++ server/cityhand.c   (working copy)
@@ -37,6 +37,7 @@
 #include "cityturn.h"
 #include "plrhand.h"
 #include "sanitycheck.h"
+#include "unittools.h"
 
 #include "cityhand.h"
 
@@ -73,6 +74,17 @@
     return;
   }
 
+  if (game.info.is_edit_mode && to == SP_COUNT) {
+    pcity->size++;
+    pcity->specialists[DEFAULT_SPECIALIST]++;
+    auto_arrange_workers(pcity);
+    send_city_info(NULL, pcity);
+    return;
+  } else if (game.info.is_edit_mode && to == SP_COUNT + 1) {
+    city_reduce_size(pcity, 1);
+    return;
+  }
+
   if (to < 0 || to >= SP_COUNT
       || from < 0 || from >= SP_COUNT
       || !city_can_use_specialist(pcity, to)
@@ -168,8 +180,8 @@
 **************************************************************************/
 void really_handle_city_sell(struct player *pplayer, struct city *pcity,
                             Impr_type_id id)
-{  
-  if (pcity->did_sell) {
+{
+  if (pcity->did_sell && !game.info.is_edit_mode) {
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND, 
                  _("You have already sold something here this turn."));
     return;
@@ -217,13 +229,14 @@
 
   assert(pcity && player_owns_city(pplayer, pcity));
  
-  if (pcity->turn_founded == game.info.turn) {
+  if (pcity->turn_founded == game.info.turn
+      && !game.info.is_edit_mode) {
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND,
                  _("Cannot buy in city created this turn."));
     return;
   }
 
-  if (pcity->did_buy) {
+  if (pcity->did_buy && !game.info.is_edit_mode) {
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND,
                  _("You have already bought this turn."));
     return;
@@ -237,7 +250,9 @@
     return;
   }
 
-  if (pcity->production.is_unit && pcity->anarchy != 0) {
+  if (pcity->production.is_unit
+      && pcity->anarchy != 0
+      && !game.info.is_edit_mode) {
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND, 
                     _("Can't buy units when city is in disorder."));
     return;
@@ -254,7 +269,7 @@
   if (cost <= 0) {
     return; /* sanity */
   }
-  if (cost > pplayer->economic.gold) {
+  if (cost > pplayer->economic.gold && !game.info.is_edit_mode) {
     /* In case something changed while player tried to buy, or player 
      * tried to cheat! */
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND,
@@ -262,14 +277,27 @@
                      pplayer->economic.gold);
     return;
   }
+  if (!game.info.is_edit_mode) {
+    pplayer->economic.gold -= cost;
+    if (pcity->shield_stock < total){
+      /* As we never put penalty on disbanded_shields, we can
+       * fully well add the missing shields there. */
+      pcity->disbanded_shields += total - pcity->shield_stock;
+      pcity->shield_stock=total; /* AI wants this -- Syela */
+      pcity->did_buy = TRUE;   /* !PS: no need to set buy flag otherwise */
+    }
+  } else {
+    /* Instantly create the desired production if in edit mode */
+    if (!pcity->production.is_unit) {
+      city_add_improvement(pcity, pcity->production.value);
+    } else {
+      struct unit *punit;
+      struct unit_type *utype = get_unit_type(pcity->production.value);
 
-  pplayer->economic.gold-=cost;
-  if (pcity->shield_stock < total){
-    /* As we never put penalty on disbanded_shields, we can
-     * fully well add the missing shields there. */
-    pcity->disbanded_shields += total - pcity->shield_stock;
-    pcity->shield_stock=total; /* AI wants this -- Syela */
-    pcity->did_buy = TRUE;     /* !PS: no need to set buy flag otherwise */
+      punit = create_unit(pplayer, pcity->tile, utype,
+                          do_make_unit_veteran(pcity, utype),
+                          pcity->id, 0);
+    }
   }
   city_refresh(pcity);
   
@@ -357,7 +385,9 @@
   }
    if (!is_build_id_unit_id && !can_build_improvement(pcity, build_id))
      return;
-  if (pcity->did_buy && pcity->shield_stock > 0) {
+  if (pcity->did_buy
+      && pcity->shield_stock > 0
+      && !game.info.is_edit_mode) {
     notify_player(pplayer, pcity->tile, E_BAD_COMMAND,
                     _("You have bought this turn, can't change."));
     return;
Index: data/misc/small.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: data/misc/small.spec
===================================================================
--- data/misc/small.spec        (revision 11621)
+++ data/misc/small.spec        (working copy)
@@ -118,4 +118,6 @@
   1, 8,  "ev.wonderobsolete"
   1, 9,  "ev.wonderwillbebuilt"
   1, 10, "ev.wonderbuilt"
+  1, 11, "s.plus"
+  1, 12, "s.minus"
 }
Index: client/citydlg_common.c
===================================================================
--- client/citydlg_common.c     (revision 11621)
+++ client/citydlg_common.c     (working copy)
@@ -798,12 +798,17 @@
   /* See really_handle_city_buy() in the server.  However this function
    * doesn't allow for error messages.  It doesn't check the cost of
    * buying; that's handled separately (and with an error message). */
+  if (!pcity
+      || impr_flag(pcity->production.value, IF_GOLD)) {
+    return FALSE;
+  }
+  if (game.info.is_edit_mode) {
+    return TRUE;
+  }
   return (can_client_issue_orders()
-         && pcity
          && pcity->owner == game.player_ptr
          && pcity->turn_founded != game.info.turn
          && !pcity->did_buy
-         && !impr_flag(pcity->production.value, IF_GOLD)
          && !(pcity->production.is_unit && pcity->anarchy != 0)
          && city_buy_cost(pcity) > 0);
 }
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
--- client/gui-gtk-2.0/citydlg.c        (revision 11621)
+++ client/gui-gtk-2.0/citydlg.c        (working copy)
@@ -95,7 +95,7 @@
 
 enum info_style { NORMAL, ORANGE, RED, NUM_INFO_STYLES };
 
-#define NUM_CITIZENS_SHOWN 25
+#define NUM_CITIZENS_SHOWN 23
 #define NUM_INFO_FIELDS 11      /* number of fields in city_info */
 #define NUM_PAGES 6             /* the number of pages in city dialog notebook 
                                  * (+1) if you change this, you must add an
@@ -656,7 +656,7 @@
   gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK);
   gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 0);
   pdialog->citizen_pixmap =
-      gtk_pixcomm_new(tileset_small_sprite_width(tileset) * NUM_CITIZENS_SHOWN,
+      gtk_pixcomm_new(tileset_small_sprite_width(tileset) * NUM_CITIZENS_SHOWN 
+ 2,
                      tileset_small_sprite_height(tileset));
   gtk_misc_set_padding(GTK_MISC(pdialog->citizen_pixmap), 2, 2);
   gtk_container_add(GTK_CONTAINER(ebox), pdialog->citizen_pixmap);
@@ -1337,7 +1337,7 @@
 *****************************************************************/
 static void city_dialog_update_citizens(struct city_dialog *pdialog)
 {
-  int i, width;
+  int i, j, width;
   struct city *pcity = pdialog->pcity;
   struct citizen_type citizens[MAX_CITY_SIZE];
 
@@ -1360,9 +1360,16 @@
 
   get_city_citizen_types(pcity, 4, citizens);
 
-  for (i = 0; i < pcity->size; i++) {
+  i = 0;
+  if (game.info.is_edit_mode) {
     gtk_pixcomm_copyto(GTK_PIXCOMM(pdialog->citizen_pixmap),
-                      get_citizen_sprite(tileset, citizens[i], i, pcity),
+                       get_arrow_sprite(tileset, 1), i++ * width, 0);
+    gtk_pixcomm_copyto(GTK_PIXCOMM(pdialog->citizen_pixmap),
+                       get_arrow_sprite(tileset, 2), i++ * width, 0);
+  }
+  for (j = 0; j < pcity->size; i++, j++) {
+    gtk_pixcomm_copyto(GTK_PIXCOMM(pdialog->citizen_pixmap),
+                      get_citizen_sprite(tileset, citizens[j], j, pcity),
                       i * width, 0);
   }
 
@@ -2347,17 +2354,32 @@
 {
   struct city_dialog *pdialog = data;
   struct city *pcity = pdialog->pcity;
-  int citnum;
+  int citnum, tlen, len;
 
   if (!can_client_issue_orders()) {
     return FALSE;
   }
 
-  if (ev->x > (pcity->size - 1) * pdialog->cwidth + 
tileset_small_sprite_width(tileset))
-    return FALSE;              /* no citizen that far to the right */
+  tlen = tileset_small_sprite_width(tileset);
+  len = (pcity->size - 1) * pdialog->cwidth + tlen;
+  if (game.info.is_edit_mode) {
+    if (ev->x > 0 && ev->x <= tlen) {
+      city_change_specialist(pcity, 0, SP_COUNT); /* add */
+      return TRUE;
+    } else if (ev->x > tlen && ev->x <= tlen * 2) {
+      city_change_specialist(pcity, 0, SP_COUNT + 1); /* reduce */
+      return TRUE;
+    } else if (ev->x > len + tlen * 2) {
+      return FALSE;
+    }
+    citnum = MIN(pcity->size - 1, (ev->x - tlen * 2) / pdialog->cwidth);
+  } else {
+    if (ev->x > len) {
+      return FALSE;            /* no citizen that far to the right */
+    }
+    citnum = MIN(pcity->size - 1, ev->x / pdialog->cwidth);
+  }
 
-  citnum = MIN(pcity->size - 1, ev->x / pdialog->cwidth);
-
   city_rotate_specialist(pcity, citnum);
 
   return TRUE;
@@ -2434,10 +2456,21 @@
   }
   value = city_buy_cost(pdialog->pcity);
 
-  if (game.player_ptr->economic.gold >= value) {
+  if (game.info.is_edit_mode) {
     shell = gtk_message_dialog_new(NULL,
         GTK_DIALOG_DESTROY_WITH_PARENT,
         GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+        _("Add %s?"), name);
+    setup_dialog(shell, pdialog->shell);
+    gtk_window_set_title(GTK_WINDOW(shell), _("Add It!"));
+    gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_NO);
+    g_signal_connect(shell, "response", G_CALLBACK(buy_callback_response),
+       pdialog);
+    gtk_window_present(GTK_WINDOW(shell));
+  } else if (game.player_ptr->economic.gold >= value) {
+    shell = gtk_message_dialog_new(NULL,
+        GTK_DIALOG_DESTROY_WITH_PARENT,
+        GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
         _("Buy %s for %d gold?\nTreasury contains %d gold."),
         name, value, game.player_ptr->economic.gold);
     setup_dialog(shell, pdialog->shell);
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
--- client/gui-gtk-2.0/gui_main.c       (revision 11621)
+++ client/gui-gtk-2.0/gui_main.c       (working copy)
@@ -702,7 +702,7 @@
   }
 
   more_arrow_pixmap
-    = gtk_image_new_from_pixbuf(sprite_get_pixbuf(get_arrow_sprite(tileset)));
+    = gtk_image_new_from_pixbuf(sprite_get_pixbuf(get_arrow_sprite(tileset, 
0)));
   gtk_widget_ref(more_arrow_pixmap);
   gtk_table_attach_defaults(GTK_TABLE(table), more_arrow_pixmap, 4, 5, 1, 2);
 
Index: client/packhand.c
===================================================================
--- client/packhand.c   (revision 11621)
+++ client/packhand.c   (working copy)
@@ -1380,6 +1380,10 @@
     update_aifill_button = TRUE;
   }
   
+  if (game.info.is_edit_mode != pinfo->is_edit_mode) {
+    popdown_all_city_dialogs();
+  }
+
   game.info = *pinfo;
 
   game.government_when_anarchy
Index: client/tilespec.c
===================================================================
--- client/tilespec.c   (revision 11621)
+++ client/tilespec.c   (working copy)
@@ -125,7 +125,7 @@
   struct sprite
     *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
     *treaty_thumb[2],     /* 0=disagree, 1=agree */
-    *right_arrow,
+    *arrow[3], /* 0=right arrow, 1=plus, 2=minus */
 
     *icon[ICON_COUNT],
 
@@ -1989,7 +1989,9 @@
     }
   }
 
-  SET_SPRITE(right_arrow, "s.right_arrow");
+  SET_SPRITE(arrow[0], "s.right_arrow");
+  SET_SPRITE(arrow[1], "s.plus");
+  SET_SPRITE(arrow[2], "s.minus");
   if (t->is_isometric) {
     SET_SPRITE(dither_tile, "t.dither_tile");
   }
@@ -4487,9 +4489,11 @@
 /**************************************************************************
   Return a sprite with the "right-arrow" theme graphic.
 **************************************************************************/
-struct sprite *get_arrow_sprite(const struct tileset *t)
+struct sprite *get_arrow_sprite(const struct tileset *t, int which)
 {
-  return t->sprites.right_arrow;
+  assert(which >= 0 && which < 3);
+  assert(t->sprites.arrow[which] != NULL);
+  return t->sprites.arrow[which];
 }
 
 /**************************************************************************
Index: client/mapctrl_common.c
===================================================================
--- client/mapctrl_common.c     (revision 11621)
+++ client/mapctrl_common.c     (working copy)
@@ -531,7 +531,7 @@
 {
   struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
-  if (game.info.is_edit_mode) {
+  if (!ptile->city && game.info.is_edit_mode) {
     editor_do_click(ptile);
   } else if (can_client_change_view() && ptile) {
     /* FIXME: Some actions here will need to check can_client_issue_orders.
Index: client/tilespec.h
===================================================================
--- client/tilespec.h   (revision 11621)
+++ client/tilespec.h   (working copy)
@@ -209,7 +209,7 @@
                                   const struct unit_type *punittype);
 struct sprite *get_sample_city_sprite(const struct tileset *t,
                                      int city_style);
-struct sprite *get_arrow_sprite(const struct tileset *t);
+struct sprite *get_arrow_sprite(const struct tileset *t, int which);
 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype);
 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off);
 const struct sprite_vector *get_unit_explode_animation(const struct

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