1 // Copyright (C) 2007 Ole Laursen
2 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include <sigc++/functors/mem_fun.h>
24 #include "city-editor-dialog.h"
26 #include "glade-helpers.h"
27 #include "ucompose.hpp"
30 #include "armyprodbase.h"
32 #include "armyproto.h"
33 #include "armyprodbase.h"
34 #include "playerlist.h"
35 #include "stacklist.h"
37 #include "CreateScenarioRandomize.h"
38 #include "GraphicsCache.h"
41 #include "select-army-dialog.h"
44 CityEditorDialog::CityEditorDialog(City *cit, CreateScenarioRandomize *randomizer)
45 : strength_column(_("Strength"), strength_renderer),
46 moves_column(_("Max Moves"), moves_renderer),
47 duration_column(_("Turns"), duration_renderer),
48 upkeep_column(_("Upkeep"), upkeep_renderer)
51 d_randomizer = randomizer;
53 Glib::RefPtr<Gtk::Builder> xml
54 = Gtk::Builder::create_from_file(get_glade_path()
55 + "/city-editor-dialog.ui");
57 xml->get_widget("dialog", dialog);
59 xml->get_widget("capital_checkbutton", capital_checkbutton);
60 capital_checkbutton->set_active(city->isCapital());
62 xml->get_widget("name_entry", name_entry);
63 name_entry->set_text(city->getName());
65 xml->get_widget("income_spinbutton", income_spinbutton);
66 income_spinbutton->set_value(city->getGold());
68 xml->get_widget("burned_checkbutton", burned_checkbutton);
69 burned_checkbutton->set_active(city->isBurnt());
71 // setup the player combo
72 player_combobox = manage(new Gtk::ComboBoxText);
75 int c = 0, player_no = 0;
76 for (Playerlist::iterator i = Playerlist::getInstance()->begin(),
77 end = Playerlist::getInstance()->end(); i != end; ++i, ++c)
80 player_combobox->append_text(player->getName());
81 if (player == city->getOwner())
85 player_combobox->set_active(player_no);
86 player_combobox->signal_changed().connect
87 (sigc::mem_fun(this, &CityEditorDialog::on_player_changed));
88 Gtk::Alignment *alignment;
89 xml->get_widget("player_alignment", alignment);
90 alignment->add(*player_combobox);
93 // setup the army list
94 army_list = Gtk::ListStore::create(army_columns);
96 xml->get_widget("army_treeview", army_treeview);
97 army_treeview->set_model(army_list);
99 army_treeview->append_column("", army_columns.image);
100 strength_renderer.property_editable() = true;
101 strength_renderer.signal_edited()
102 .connect(sigc::mem_fun(*this, &CityEditorDialog::on_strength_edited));
103 strength_column.set_cell_data_func
105 sigc::mem_fun(*this, &CityEditorDialog::cell_data_strength));
106 army_treeview->append_column(strength_column);
108 moves_renderer.property_editable() = true;
109 moves_renderer.signal_edited()
110 .connect(sigc::mem_fun(*this, &CityEditorDialog::on_moves_edited));
111 moves_column.set_cell_data_func
113 sigc::mem_fun(*this, &CityEditorDialog::cell_data_moves));
114 army_treeview->append_column(moves_column);
116 upkeep_renderer.property_editable() = true;
117 upkeep_renderer.signal_edited()
118 .connect(sigc::mem_fun(*this, &CityEditorDialog::on_upkeep_edited));
119 upkeep_column.set_cell_data_func
121 sigc::mem_fun(*this, &CityEditorDialog::cell_data_upkeep));
122 army_treeview->append_column(upkeep_column);
124 duration_renderer.property_editable() = true;
125 duration_renderer.signal_edited()
126 .connect(sigc::mem_fun(*this, &CityEditorDialog::on_turns_edited));
127 duration_column.set_cell_data_func
129 sigc::mem_fun(*this, &CityEditorDialog::cell_data_turns));
130 army_treeview->append_column(strength_column);
132 army_treeview->append_column(_("Name"), army_columns.name);
134 xml->get_widget("add_button", add_button);
135 xml->get_widget("remove_button", remove_button);
136 xml->get_widget("randomize_armies_button", randomize_armies_button);
137 xml->get_widget("randomize_name_button", randomize_name_button);
138 xml->get_widget("randomize_income_button", randomize_income_button);
140 add_button->signal_clicked().connect(
141 sigc::mem_fun(this, &CityEditorDialog::on_add_clicked));
142 remove_button->signal_clicked().connect(
143 sigc::mem_fun(this, &CityEditorDialog::on_remove_clicked));
144 randomize_armies_button->signal_clicked().connect(
145 sigc::mem_fun(this, &CityEditorDialog::on_randomize_armies_clicked));
146 randomize_name_button->signal_clicked().connect(
147 sigc::mem_fun(this, &CityEditorDialog::on_randomize_name_clicked));
148 randomize_income_button->signal_clicked().connect(
149 sigc::mem_fun(this, &CityEditorDialog::on_randomize_income_clicked));
151 army_treeview->get_selection()->signal_changed()
152 .connect(sigc::mem_fun(this, &CityEditorDialog::on_selection_changed));
154 for (unsigned int i = 0; i < city->getMaxNoOfProductionBases(); i++)
156 const ArmyProdBase* a = city->getProductionBase(i);
161 CityEditorDialog::~CityEditorDialog()
166 void CityEditorDialog::set_parent_window(Gtk::Window &parent)
168 dialog->set_transient_for(parent);
169 //dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
172 void CityEditorDialog::change_city_ownership()
175 Player *player = get_selected_player();
176 if (player == city->getOwner()) //no change? do nothing.
178 city->setOwner(player);
179 //look for stacks in the city, and set them to this player
180 for (unsigned int x = 0; x < city->getSize(); x++)
182 for (unsigned int y = 0; y < city->getSize(); y++)
184 Stack *s = GameMap::getStack(city->getPos() + Vector<int>(x,y));
186 Stacklist::changeOwnership(s, player);
191 int CityEditorDialog::run()
194 int response = dialog->run();
196 if (response == Gtk::RESPONSE_ACCEPT) // accepted
200 bool capital = capital_checkbutton->get_active();
203 // make sure player doesn't have other capitals
204 Citylist* cl = Citylist::getInstance();
205 for (Citylist::iterator i = cl->begin(); i != cl->end(); ++i)
206 if ((*i)->isCapital() && (*i)->getOwner() == city->getOwner())
208 (*i)->setCapital(false);
209 (*i)->setCapitalOwner(NULL);
211 city->setCapital(true);
212 city->setCapitalOwner(city->getOwner());
216 city->setCapital(false);
217 city->setCapitalOwner(NULL);
220 city->setName(name_entry->get_text());
221 city->setGold(income_spinbutton->get_value_as_int());
222 city->setBurnt(burned_checkbutton->get_active());
224 // set production slots
226 for (Gtk::TreeIter i = army_list->children().begin(),
227 end = army_list->children().end(); i != end; ++i, ++c)
229 const ArmyProdBase *a = (*i)[army_columns.army];
230 ArmyProdBase *army = new ArmyProdBase(*a);
231 army->setStrength((*i)[army_columns.strength]);
232 army->setProduction((*i)[army_columns.duration]);
233 city->addProductionBase(c, army);
235 // FIXME: use (*i)[army_columns.duration] to set special city
236 // production ability
238 for (; c < city->getMaxNoOfProductionBases(); ++c)
239 city->removeProductionBase(c);
240 //set owner of the city
241 change_city_ownership();
245 if (name_entry->get_text() != City::getDefaultName())
246 d_randomizer->pushRandomCityName(name_entry->get_text());
251 void CityEditorDialog::on_add_clicked()
253 SelectArmyDialog d(city->getOwner());
254 d.set_parent_window(*dialog);
257 const ArmyProto *army = d.get_selected_army();
259 add_army(new ArmyProdBase(*army));
263 void CityEditorDialog::on_remove_clicked()
265 Gtk::TreeIter i = army_treeview->get_selection()->get_selected();
271 set_button_sensitivity();
274 void CityEditorDialog::on_randomize_armies_clicked()
276 const ArmyProdBase *army;
278 city->setRandomArmytypes(true, 1);
279 for (unsigned int i = 0; i < city->getMaxNoOfProductionBases(); i++)
281 army = city->getProductionBase(i);
285 set_button_sensitivity();
288 void CityEditorDialog::on_randomize_name_clicked()
290 std::string existing_name = name_entry->get_text();
291 if (existing_name == City::getDefaultName())
292 name_entry->set_text(d_randomizer->popRandomCityName());
295 name_entry->set_text(d_randomizer->popRandomCityName());
296 d_randomizer->pushRandomCityName(existing_name);
300 void CityEditorDialog::on_randomize_income_clicked()
303 gold = d_randomizer->getRandomCityIncome(capital_checkbutton->get_active());
304 income_spinbutton->set_value(gold);
307 void CityEditorDialog::add_army(const ArmyProdBase *a)
309 Player *player = get_selected_player();
310 GraphicsCache *gc = GraphicsCache::getInstance();
311 Gtk::TreeIter i = army_list->append();
312 (*i)[army_columns.army] = a;
313 (*i)[army_columns.image] = gc->getArmyPic(player->getArmyset(),
314 a->getTypeId(), player,
316 (*i)[army_columns.strength] = a->getStrength();
317 (*i)[army_columns.moves] = a->getMaxMoves();
318 (*i)[army_columns.upkeep] = a->getUpkeep();
319 (*i)[army_columns.duration] = a->getProduction();
320 (*i)[army_columns.name] = a->getName();
321 army_treeview->get_selection()->select(i);
323 set_button_sensitivity();
326 void CityEditorDialog::on_selection_changed()
328 set_button_sensitivity();
331 void CityEditorDialog::set_button_sensitivity()
333 Gtk::TreeIter i = army_treeview->get_selection()->get_selected();
334 unsigned int armies = army_list->children().size();
335 add_button->set_sensitive(armies < city->getMaxNoOfProductionBases());
336 remove_button->set_sensitive(i);
339 void CityEditorDialog::cell_data_strength(Gtk::CellRenderer *renderer,
340 const Gtk::TreeIter& i)
342 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_adjustment()
343 = new Gtk::Adjustment((*i)[army_columns.strength],
344 MIN_STRENGTH_FOR_ARMY_UNITS,
345 MAX_STRENGTH_FOR_ARMY_UNITS, 1);
346 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_text() =
347 String::ucompose("%1", (*i)[army_columns.strength]);
350 void CityEditorDialog::on_strength_edited(const Glib::ustring &path,
351 const Glib::ustring &new_text)
353 int str = atoi(new_text.c_str());
354 if (str < (int)MIN_STRENGTH_FOR_ARMY_UNITS ||
355 str > (int)MAX_STRENGTH_FOR_ARMY_UNITS)
357 (*army_list->get_iter(Gtk::TreePath(path)))[army_columns.strength] = str;
360 void CityEditorDialog::cell_data_moves(Gtk::CellRenderer *renderer,
361 const Gtk::TreeIter& i)
363 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_adjustment()
364 = new Gtk::Adjustment((*i)[army_columns.moves],
365 MIN_MOVES_FOR_ARMY_UNITS,
366 MAX_MOVES_FOR_ARMY_UNITS, 1);
367 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_text() =
368 String::ucompose("%1", (*i)[army_columns.moves]);
371 void CityEditorDialog::on_moves_edited(const Glib::ustring &path,
372 const Glib::ustring &new_text)
374 int moves = atoi(new_text.c_str());
375 if (moves < (int)MIN_MOVES_FOR_ARMY_UNITS ||
376 moves > (int)MAX_MOVES_FOR_ARMY_UNITS)
378 (*army_list->get_iter(Gtk::TreePath(path)))[army_columns.moves] = moves;
381 void CityEditorDialog::cell_data_turns(Gtk::CellRenderer *renderer,
382 const Gtk::TreeIter& i)
384 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_adjustment()
385 = new Gtk::Adjustment((*i)[army_columns.duration],
386 MIN_PRODUCTION_TURNS_FOR_ARMY_UNITS,
387 MAX_PRODUCTION_TURNS_FOR_ARMY_UNITS, 1);
388 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_text() =
389 String::ucompose("%1", (*i)[army_columns.duration]);
392 void CityEditorDialog::on_turns_edited(const Glib::ustring &path,
393 const Glib::ustring &new_text)
395 int turns = atoi(new_text.c_str());
396 if (turns < (int)MIN_PRODUCTION_TURNS_FOR_ARMY_UNITS ||
397 turns > (int)MAX_PRODUCTION_TURNS_FOR_ARMY_UNITS)
399 (*army_list->get_iter(Gtk::TreePath(path)))[army_columns.duration] = turns;
402 void CityEditorDialog::cell_data_upkeep(Gtk::CellRenderer *renderer,
403 const Gtk::TreeIter& i)
405 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_adjustment()
406 = new Gtk::Adjustment((*i)[army_columns.upkeep], 0, 20, 1);
407 dynamic_cast<Gtk::CellRendererSpin*>(renderer)->property_text() =
408 String::ucompose("%1", (*i)[army_columns.upkeep]);
411 void CityEditorDialog::on_upkeep_edited(const Glib::ustring &path,
412 const Glib::ustring &new_text)
414 int upkeep = atoi(new_text.c_str());
415 if (upkeep < (int) MIN_UPKEEP_FOR_ARMY_UNITS ||
416 upkeep > (int) MAX_UPKEEP_FOR_ARMY_UNITS)
418 (*army_list->get_iter(Gtk::TreePath(path)))[army_columns.upkeep] = upkeep;
422 Player *CityEditorDialog::get_selected_player()
424 int c = 0, row = player_combobox->get_active_row_number();
425 Player *player = Playerlist::getInstance()->getNeutral();
426 for (Playerlist::iterator i = Playerlist::getInstance()->begin(),
427 end = Playerlist::getInstance()->end(); i != end; ++i, ++c)
436 void CityEditorDialog::on_player_changed()
438 GraphicsCache *gc = GraphicsCache::getInstance();
440 Player *player = get_selected_player();
441 for (Gtk::TreeIter j = army_list->children().begin(),
442 jend = army_list->children().end(); j != jend; ++j)
444 const ArmyProdBase *a = (*j)[army_columns.army];
445 (*j)[army_columns.image] = gc->getArmyPic(player->getArmyset(),
447 player, NULL)->to_pixbuf();