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
24 #include <sigc++/functors/mem_fun.h>
27 #include "hero-dialog.h"
29 #include "glade-helpers.h"
30 #include "image-helpers.h"
31 #include "input-helpers.h"
32 #include "ucompose.hpp"
37 #include "GraphicsCache.h"
39 #include "MapBackpack.h"
42 HeroDialog::HeroDialog(Hero *h, Vector<int> p)
44 inhibit_hero_changed = false;
48 Glib::RefPtr<Gtk::Builder> xml
49 = Gtk::Builder::create_from_file(get_glade_path()
52 xml->get_widget("dialog", dialog);
54 window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
55 xml->get_widget("map_image", map_image);
57 std::list<Hero*> heroes;
58 heroes = Playerlist::getActiveplayer()->getHeroes();
59 heroesmap = new HeroesMap(heroes);
61 heroesmap->setSelectedHero(hero);
64 Player *p = Playerlist::getActiveplayer();
65 hero = *heroes.begin();
66 pos = p->getPositionOfArmyById(hero->getId());
67 heroesmap->setSelectedHero(hero);
69 heroesmap->map_changed.connect(
70 sigc::mem_fun(this, &HeroDialog::on_map_changed));
71 Gtk::EventBox *map_eventbox;
72 xml->get_widget("map_eventbox", map_eventbox);
73 map_eventbox->add_events(Gdk::BUTTON_PRESS_MASK);
74 map_eventbox->signal_button_press_event().connect(
75 sigc::mem_fun(*this, &HeroDialog::on_map_mouse_button_event));
77 xml->get_widget("info_label1", info_label1);
78 xml->get_widget("info_label2", info_label2);
80 xml->get_widget("drop_button", drop_button);
81 xml->get_widget("pickup_button", pickup_button);
82 drop_button->signal_clicked()
83 .connect(sigc::mem_fun(this, &HeroDialog::on_drop_clicked));
84 pickup_button->signal_clicked()
85 .connect(sigc::mem_fun(this, &HeroDialog::on_pickup_clicked));
87 xml->get_widget("next_button", next_button);
88 xml->get_widget("prev_button", prev_button);
89 next_button->signal_clicked()
90 .connect(sigc::mem_fun(this, &HeroDialog::on_next_clicked));
91 prev_button->signal_clicked()
92 .connect(sigc::mem_fun(this, &HeroDialog::on_prev_clicked));
93 if (heroes.size() <= 1)
95 next_button->set_sensitive(false);
96 prev_button->set_sensitive(false);
99 heroes_list = Gtk::ListStore::create(heroes_columns);
100 xml->get_widget("heroes_treeview", heroes_treeview);
101 heroes_treeview->set_model(heroes_list);
102 heroes_treeview->append_column(_("Hero"), heroes_columns.name);
104 heroes_list->clear();
106 for (std::list<Hero*>::iterator it = heroes.begin(); it != heroes.end();
112 Gtk::TreeModel::Row row;
113 row = heroes_treeview->get_model()->children()[count];
114 heroes_treeview->get_selection()->select(row);
118 heroes_treeview->get_selection()->signal_changed()
119 .connect(sigc::mem_fun(this, &HeroDialog::on_hero_changed));
121 item_list = Gtk::ListStore::create(item_columns);
122 xml->get_widget("treeview", item_treeview);
123 item_treeview->set_model(item_list);
124 item_treeview->append_column("", item_columns.image);
125 item_treeview->append_column(_("Name"), item_columns.name);
126 item_treeview->append_column(_("Attributes"), item_columns.attributes);
127 item_treeview->append_column(_("Status"), item_columns.status);
129 item_treeview->get_selection()->signal_changed()
130 .connect(sigc::mem_fun(this, &HeroDialog::on_item_selection_changed));
132 events_list = Gtk::ListStore::create(events_columns);
133 xml->get_widget("events_treeview", events_treeview);
134 events_treeview->append_column("", events_columns.desc);
135 events_treeview->set_model(events_list);
136 events_list->clear();
138 on_item_selection_changed();
141 HeroDialog::~HeroDialog()
146 void HeroDialog::addHistoryEvent(History *history)
148 Glib::ustring s = "";
149 Gtk::TreeIter i = events_list->append();
151 switch (history->getType())
153 case History::FOUND_SAGE:
155 History_FoundSage *ev;
156 ev = static_cast<History_FoundSage *>(history);
157 s = String::ucompose(_("%1 finds a sage!"), ev->getHeroName());
160 case History::HERO_EMERGES:
162 History_HeroEmerges *ev;
163 ev = static_cast<History_HeroEmerges *>(history);
164 s = String::ucompose(_("%1 emerges in %2!"), ev->getHeroName(),
168 case History::HERO_QUEST_STARTED:
170 History_HeroQuestStarted *ev;
171 ev = static_cast<History_HeroQuestStarted*>(history);
172 s = String::ucompose(_("%1 begins a quest!"), ev->getHeroName());
175 case History::HERO_QUEST_COMPLETED:
177 History_HeroQuestCompleted *ev;
178 ev = static_cast<History_HeroQuestCompleted *>(history);
179 s = String::ucompose(_("%1 finishes a quest!"), ev->getHeroName());
182 case History::HERO_KILLED_IN_CITY:
184 History_HeroKilledInCity *ev;
185 ev = static_cast<History_HeroKilledInCity *>(history);
186 s = String::ucompose(_("%1 is killed in %2!"), ev->getHeroName(),
190 case History::HERO_KILLED_IN_BATTLE:
192 History_HeroKilledInBattle *ev;
193 ev = static_cast<History_HeroKilledInBattle *>(history);
194 s = String::ucompose(_("%1 is killed in battle!"), ev->getHeroName());
197 case History::HERO_KILLED_SEARCHING:
199 History_HeroKilledSearching *ev;
200 ev = static_cast<History_HeroKilledSearching *>(history);
201 s = String::ucompose(_("%1 is killed while searching!"),
205 case History::HERO_CITY_WON:
207 History_HeroCityWon *ev;
208 ev = static_cast<History_HeroCityWon *>(history);
209 s = String::ucompose(_("%1 conquers %2!"), ev->getHeroName(),
213 case History::HERO_FINDS_ALLIES:
215 History_HeroFindsAllies *ev;
216 ev = static_cast<History_HeroFindsAllies*>(history);
217 s = String::ucompose(_("%1 finds allies!"), ev->getHeroName());
225 (*i)[events_columns.desc] = s;
226 (*i)[events_columns.history] = history;
229 void HeroDialog::set_parent_window(Gtk::Window &parent)
231 dialog->set_transient_for(parent);
232 //dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
235 void HeroDialog::hide()
240 void HeroDialog::run()
243 heroesmap->draw(Playerlist::getActiveplayer());
244 GameMap *gm = GameMap::getInstance();
248 if (gm->getTile(pos)->getBackpack()->size() > 0 &&
249 gm->getTile(pos)->getMaptileType() == Tile::WATER)
251 // splash, items lost forever
252 while (gm->getTile(pos)->getBackpack()->size())
254 MapBackpack::iterator i = gm->getTile(pos)->getBackpack()->begin();
255 gm->getTile(pos)->getBackpack()->removeFromBackpack(*i);
260 void HeroDialog::update_hero_list()
262 inhibit_hero_changed = true;
263 std::list<Hero*> heroes;
264 heroes = Playerlist::getActiveplayer()->getHeroes();
266 for (std::list<Hero*>::iterator it = heroes.begin(); it != heroes.end();
271 Gtk::TreeModel::Row row;
272 row = heroes_treeview->get_model()->children()[count];
273 heroes_treeview->get_selection()->select(row);
277 inhibit_hero_changed = false;
280 void HeroDialog::on_hero_changed()
282 if (inhibit_hero_changed == true)
284 Glib::RefPtr<Gtk::TreeSelection> selection = heroes_treeview->get_selection();
285 Gtk::TreeModel::iterator iterrow = selection->get_selected();
289 Gtk::TreeModel::Row row = *iterrow;
290 hero = row[heroes_columns.hero];
291 pos = Playerlist::getActiveplayer()->getPositionOfArmyById(hero->getId());
292 heroesmap->setSelectedHero(hero);
294 heroesmap->draw(Playerlist::getActiveplayer());
299 void HeroDialog::on_item_selection_changed()
301 Gtk::TreeIter i = item_treeview->get_selection()->get_selected();
304 bool droppable = (*i)[item_columns.status] == _("In backpack");
305 drop_button->set_sensitive(droppable);
306 pickup_button->set_sensitive(!droppable);
310 drop_button->set_sensitive(false);
311 pickup_button->set_sensitive(false);
315 void HeroDialog::on_drop_clicked()
317 Gtk::TreeIter i = item_treeview->get_selection()->get_selected();
320 Item *item = (*i)[item_columns.item];
321 hero->getOwner()->heroDropItem (hero, item, pos);
322 (*i)[item_columns.status] = _("On the ground");
323 on_item_selection_changed();
324 fill_in_info_labels();
328 void HeroDialog::on_next_clicked()
330 std::list<Hero*> heroes;
331 heroes = Playerlist::getActiveplayer()->getHeroes();
332 std::list<Hero*>::iterator next;
333 next = find (heroes.begin(), heroes.end(), hero);
334 if (next != heroes.end())
337 if (next == heroes.end())
338 next = heroes.begin();
340 heroesmap->setSelectedHero(hero);
342 heroesmap->draw(Playerlist::getActiveplayer());
346 void HeroDialog::on_prev_clicked()
348 std::list<Hero*> heroes;
349 heroes = Playerlist::getActiveplayer()->getHeroes();
350 std::list<Hero*>::reverse_iterator prev;
351 prev = find (heroes.rbegin(), heroes.rend(), hero);
352 if (prev != heroes.rend())
355 if (prev == heroes.rend())
356 prev = heroes.rbegin();
358 heroesmap->setSelectedHero(hero);
360 heroesmap->draw(Playerlist::getActiveplayer());
364 void HeroDialog::on_pickup_clicked()
366 Gtk::TreeIter i = item_treeview->get_selection()->get_selected();
369 Item *item = (*i)[item_columns.item];
370 if (item->getPlanted() == true)
371 item->setPlanted(false);
372 hero->getOwner()->heroPickupItem (hero, item, pos);
373 (*i)[item_columns.status] = _("In backpack");
374 on_item_selection_changed();
375 fill_in_info_labels();
379 void HeroDialog::add_hero(Hero *h)
381 Gtk::TreeIter i = heroes_list->append();
382 (*i)[heroes_columns.name] = h->getName();
383 (*i)[heroes_columns.hero] = h;
386 void HeroDialog::add_item(Item *item, bool in_backpack)
388 Gtk::TreeIter i = item_list->append();
389 (*i)[item_columns.name] = item->getName();
391 (*i)[item_columns.attributes] = item->getBonusDescription();
394 (*i)[item_columns.status] = _("In backpack");
396 (*i)[item_columns.status] = _("On the ground");
398 (*i)[item_columns.item] = item;
401 void HeroDialog::fill_in_info_labels()
405 // fill in first column
406 Backpack *backpack = hero->getBackpack();
407 for (Backpack::iterator i = backpack->begin(); i != backpack->end(); ++i)
409 if ((*i)->getBonus(Item::ADD1STR))
411 if ((*i)->getBonus(Item::ADD2STR))
413 if ((*i)->getBonus(Item::ADD3STR))
416 s += String::ucompose(_("Battle: %1"), bonus);
420 for (Backpack::iterator i = backpack->begin(); i != backpack->end(); ++i)
422 if ((*i)->getBonus(Item::ADD1STACK))
424 if ((*i)->getBonus(Item::ADD2STACK))
426 if ((*i)->getBonus(Item::ADD3STACK))
430 //now add natural command
431 bonus += hero->calculateNaturalCommand ();
433 s += String::ucompose(_("Command: %1"), bonus);
435 s += String::ucompose(_("Level: %1"), hero->getLevel());
437 s += String::ucompose(_("Experience: %1"),
438 std::setprecision(3), hero->getXP());
439 info_label1->set_text(s);
441 // fill in second column
443 // note to translators: %1 is melee strength, %2 is ranged strength
444 s += String::ucompose(_("Strength: %1"),
445 hero->getStat(Army::STRENGTH));
447 // note to translators: %1 is remaining moves, %2 is total moves
448 s += String::ucompose(_("Moves: %1/%2"),
449 hero->getMoves(), hero->getStat(Army::MOVES));
451 s += String::ucompose(_("Upkeep: %1"), hero->getUpkeep());
452 info_label2->set_text(s);
455 void HeroDialog::on_map_changed(Glib::RefPtr<Gdk::Pixmap> map)
457 map_image->property_pixmap() = map;
460 bool HeroDialog::on_map_mouse_button_event(GdkEventButton *e)
462 if (e->type != GDK_BUTTON_PRESS)
463 return true; // useless event
465 heroesmap->mouse_button_event(to_input_event(e));
467 hero = heroesmap->getSelectedHero();
468 pos = Playerlist::getActiveplayer()->getPositionOfArmyById(hero->getId());
470 heroesmap->draw(Playerlist::getActiveplayer());
475 void HeroDialog::show_hero()
477 set_title(hero->getName());
479 fill_in_info_labels();
480 std::list<History* > events;
481 events = hero->getOwner()->getHistoryForHeroId(hero->getId());
482 events_list->clear();
483 for (std::list<History*>::iterator i = events.begin(); i != events.end();
487 // populate the item list
489 Backpack *backpack = hero->getBackpack();
490 for (Backpack::iterator i = backpack->begin(); i != backpack->end(); ++i)
493 MapBackpack *ground = GameMap::getInstance()->getTile(pos)->getBackpack();
494 for (MapBackpack::iterator i = ground->begin(); i != ground->end(); i++)