initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / destination-dialog.cpp
1 //  Copyright (C) 2007 Ole Laursen
2 //  Copyright (C) 2007, 2008, 2009 Ben Asselstine
3 //
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.
8 //
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.
13 //
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 
17 //  02110-1301, USA.
18
19 #include <config.h>
20
21 #include <gtkmm.h>
22 #include <sigc++/functors/mem_fun.h>
23
24 #include "destination-dialog.h"
25
26 #include "glade-helpers.h"
27 #include "image-helpers.h"
28 #include "input-helpers.h"
29 #include "ucompose.hpp"
30 #include "defs.h"
31 #include "GameMap.h"
32 #include "city.h"
33 #include "armysetlist.h"
34 #include "armyprodbase.h"
35 #include "citylist.h"
36 #include "GraphicsCache.h"
37 #include "vectoredunitlist.h"
38 #include "vectoredunit.h"
39
40 DestinationDialog::DestinationDialog(City *c, bool *see_all)
41 {
42   d_see_all = see_all;
43     city = c;
44     
45     Glib::RefPtr<Gtk::Builder> xml
46         = Gtk::Builder::create_from_file(get_glade_path()
47                                     + "/destination-dialog.ui");
48
49     xml->get_widget("dialog", dialog);
50     decorate(dialog);
51     window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
52
53     xml->get_widget("map_image", map_image);
54     xml->get_widget("see_all_togglebutton", see_all_toggle);
55     xml->get_widget("vector_togglebutton", vector_toggle);
56     xml->get_widget("change_togglebutton", change_toggle);
57     xml->get_widget("current_label", current_label);
58     xml->get_widget("current_image", current_image);
59     xml->get_widget("turns_label", turns_label);
60     xml->get_widget("one_turn_away_image", one_turn_away_image);
61     xml->get_widget("two_turns_away_image", two_turns_away_image);
62     xml->get_widget("next_turn_1_image", next_turn_1_image);
63     xml->get_widget("next_turn_2_image", next_turn_2_image);
64     xml->get_widget("next_turn_3_image", next_turn_3_image);
65     xml->get_widget("next_turn_4_image", next_turn_4_image);
66     xml->get_widget("turn_after_1_image", turn_after_1_image);
67     xml->get_widget("turn_after_2_image", turn_after_2_image);
68     xml->get_widget("turn_after_3_image", turn_after_3_image);
69     xml->get_widget("turn_after_4_image", turn_after_4_image);
70
71     see_all_toggle->signal_toggled().connect(
72       sigc::bind(sigc::mem_fun(this, &DestinationDialog::on_see_all_toggled),
73                                see_all_toggle));
74     vector_toggle->signal_toggled().connect(
75       sigc::bind(sigc::mem_fun(this, &DestinationDialog::on_vector_toggled),
76                                vector_toggle));
77     change_toggle->signal_toggled().connect(
78       sigc::bind(sigc::mem_fun(this, &DestinationDialog::on_change_toggled),
79                                change_toggle));
80
81     vectormap = new VectorMap(c, VectorMap::SHOW_ORIGIN_CITY_VECTORING, false);
82     vectormap->map_changed.connect(
83         sigc::mem_fun(this, &DestinationDialog::on_map_changed));
84
85     Gtk::EventBox *map_eventbox;
86     xml->get_widget("map_eventbox", map_eventbox);
87     map_eventbox->add_events(Gdk::BUTTON_PRESS_MASK);
88     map_eventbox->signal_button_press_event().connect(
89         sigc::mem_fun(*this, &DestinationDialog::on_map_mouse_button_event));
90   fill_in_vectoring_info();
91 }
92
93 DestinationDialog::~DestinationDialog()
94 {
95   delete dialog;
96   delete vectormap;
97 }
98
99 void DestinationDialog::set_parent_window(Gtk::Window &parent)
100 {
101     dialog->set_transient_for(parent);
102     //dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
103 }
104
105 void DestinationDialog::hide()
106 {
107   dialog->hide();
108 }
109
110 void DestinationDialog::run()
111 {
112     vectormap->resize();
113     vectormap->draw(Playerlist::getActiveplayer());
114     see_all_toggle->set_active(*d_see_all);
115     dialog->show();
116     dialog->run();
117 }
118
119 void DestinationDialog::on_map_changed(Glib::RefPtr<Gdk::Pixmap> map)
120 {
121   if (vectormap->getClickAction() == VectorMap::CLICK_SELECTS &&
122       vector_toggle->get_active() == true)
123     {
124       vector_toggle->set_active(false);
125     }
126   else
127     {
128       city = vectormap->getCity();
129       fill_in_vectoring_info();
130     }
131   map_image->property_pixmap() = map;
132 }
133
134 bool DestinationDialog::on_map_mouse_button_event(GdkEventButton *e)
135 {
136     if (e->type != GDK_BUTTON_PRESS)
137         return true;    // useless event
138     
139     vectormap->mouse_button_event(to_input_event(e));
140     city = vectormap->getCity();
141     fill_in_vectoring_info();
142     
143     return true;
144 }
145
146 void DestinationDialog::on_see_all_toggled(Gtk::ToggleButton *toggle)
147 {
148   *d_see_all = toggle->get_active();
149   if (*d_see_all)
150     vectormap->setShowVectoring(VectorMap::SHOW_ALL_VECTORING);
151   else
152     vectormap->setShowVectoring(VectorMap::SHOW_ORIGIN_CITY_VECTORING);
153   vectormap->draw(Playerlist::getActiveplayer());
154 }
155
156 void DestinationDialog::on_vector_toggled(Gtk::ToggleButton *toggle)
157 {
158 // the idea here is that we click on the toggle,
159 // and then after we click on the map, it gets untoggled
160 // we act when it's untoggled.
161   if (toggle->get_active() == false)
162     {
163       vectormap->setClickAction(VectorMap::CLICK_SELECTS);
164       vectormap->draw(Playerlist::getActiveplayer());
165       fill_in_vectoring_info();
166     }
167   else
168     {
169       vectormap->setClickAction(VectorMap::CLICK_VECTORS);
170       vectormap->draw(Playerlist::getActiveplayer());
171     }
172 }
173
174 void DestinationDialog::on_change_toggled(Gtk::ToggleButton *toggle)
175 {
176 // the idea here is that we click on the toggle,
177 // and then after we click on the map, it gets untoggled
178 // we act when it's untoggled.
179   if (toggle->get_active() == false)
180     {
181       vectormap->setClickAction(VectorMap::CLICK_SELECTS);
182       vectormap->draw(Playerlist::getActiveplayer());
183       fill_in_vectoring_info();
184     }
185   else
186     {
187       vectormap->setClickAction(VectorMap::CLICK_CHANGES_DESTINATION);
188       vectormap->draw(Playerlist::getActiveplayer());
189     }
190 }
191
192 void DestinationDialog::fill_in_vectoring_info()
193 {
194   std::list<VectoredUnit*> vectored;
195   std::list<VectoredUnit*>::const_iterator it;
196   VectoredUnitlist *vul = VectoredUnitlist::getInstance();
197   set_title(city->getName());
198
199   Player *player = city->getOwner();
200   unsigned int as = player->getArmyset();
201   Glib::RefPtr<Gdk::Pixbuf> pic;
202   GraphicsCache *gc = GraphicsCache::getInstance();
203   int slot = city->getActiveProductionSlot();
204   Glib::RefPtr<Gdk::Pixbuf> s
205     = GraphicsCache::getInstance()->getArmyPic(as, 0, player, NULL)->to_pixbuf();
206   Glib::RefPtr<Gdk::Pixbuf> empty_pic
207     = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, s->get_width(), s->get_height());
208   empty_pic->fill(0x00000000);
209
210   vector_toggle->set_sensitive(slot != -1 ? true : false);
211
212   Citylist *cl = Citylist::getInstance();
213   bool target = cl->isVectoringTarget(city);
214   change_toggle->set_sensitive(target);
215
216   one_turn_away_image->set(empty_pic);
217   two_turns_away_image->set(empty_pic);
218   next_turn_1_image->set(empty_pic);
219   next_turn_2_image->set(empty_pic);
220   next_turn_3_image->set(empty_pic);
221   next_turn_4_image->set(empty_pic);
222   turn_after_1_image->set(empty_pic);
223   turn_after_2_image->set(empty_pic);
224   turn_after_3_image->set(empty_pic);
225   turn_after_4_image->set(empty_pic);
226
227   Glib::ustring s1;
228   Glib::ustring s4 = _("Current:");
229
230   if (slot == -1)
231     {
232       pic = empty_pic;
233       turns_label->set_markup("");
234     }
235   else
236     {
237       const ArmyProdBase* a = city->getProductionBase(slot);
238       pic = gc->getArmyPic(as, a->getTypeId(), player, NULL)->to_pixbuf();
239       s1 = String::ucompose(_("%1t"), city->getDuration());
240       turns_label->set_markup("<i>" + s1 + "</i>");
241     }
242     
243   current_image->property_pixbuf() = pic;
244   current_label->set_markup("<i>" + s4 + "</i>");
245
246   //show the units that have been vectored from this city
247   vul->getVectoredUnitsComingFrom(city->getPos(), vectored);
248   for (it = vectored.begin(); it != vectored.end(); it++)
249     {
250       int armytype = (*it)->getArmy()->getTypeId();
251       if ((*it)->getDuration() == 2)
252         {
253           pic = gc->getArmyPic(as, armytype, player, NULL)->to_pixbuf();
254           one_turn_away_image->property_pixbuf() = pic;
255         }
256       else if ((*it)->getDuration() == 1)
257         {
258           pic = gc->getArmyPic(as, armytype, player, NULL)->to_pixbuf();
259           two_turns_away_image->property_pixbuf() = pic;
260         }
261     }
262
263   //show the units that are arriving into this city
264   vectored.clear();
265   vul->getVectoredUnitsGoingTo(city, vectored);
266   int count = 0;
267   Gtk::Image *image = next_turn_1_image;
268   for (it = vectored.begin(); it != vectored.end(); it++)
269     {
270       if ((*it)->getDuration() != 1)
271         continue;
272
273       switch (count)
274         {
275           case 0: image = next_turn_1_image; break;
276           case 1: image = next_turn_2_image; break;
277           case 2: image = next_turn_3_image; break;
278           case 3: image = next_turn_4_image; break;
279         }
280       pic = gc->getArmyPic(as, (*it)->getArmy()->getTypeId(), player, NULL)->to_pixbuf();
281       image->property_pixbuf() = pic;
282       count++;
283     }
284   count = 0;
285   for (it = vectored.begin(); it != vectored.end(); it++)
286     {
287       if ((*it)->getDuration() != 2)
288         continue;
289       switch (count)
290         {
291           case 0: image = turn_after_1_image; break;
292           case 1: image = turn_after_2_image; break;
293           case 2: image = turn_after_3_image; break;
294           case 3: image = turn_after_4_image; break;
295         }
296       pic = gc->getArmyPic(as, (*it)->getArmy()->getTypeId(), player, NULL)->to_pixbuf();
297       image->property_pixbuf() = pic;
298       count++;
299     }
300 }