initial commit, lordsawar source, slightly modified
[lordsawar] / src / editor / select-army-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 #include <assert.h>
24
25 #include "select-army-dialog.h"
26
27 #include "glade-helpers.h"
28 #include "gui/image-helpers.h"
29 #include "gui/input-helpers.h"
30 #include "ucompose.hpp"
31 #include "defs.h"
32 #include "armyproto.h"
33 #include "GraphicsCache.h"
34 #include "armysetlist.h"
35
36 SelectArmyDialog::SelectArmyDialog(Player *p, bool hero_too, 
37                                    bool defends_ruins, bool awardable)
38 {
39   army_info_tip = NULL;
40   d_hero_too = hero_too;
41     d_defends_ruins = defends_ruins;
42     player = p;
43     d_awardable = awardable;
44     selected_army = 0;
45     
46     Glib::RefPtr<Gtk::Builder> xml
47         = Gtk::Builder::create_from_file(get_glade_path()
48                                     + "/select-army-dialog.ui");
49
50     xml->get_widget("dialog", dialog);
51     
52     xml->get_widget("army_info_label1", army_info_label1);
53     xml->get_widget("army_info_label2", army_info_label2);
54     xml->get_widget("select_button", select_button);
55
56     xml->get_widget("army_toggles_table", toggles_table);
57
58   fill_in_army_toggles();
59 }
60
61 SelectArmyDialog::~SelectArmyDialog()
62 {
63   delete dialog;
64 }
65 void SelectArmyDialog::set_parent_window(Gtk::Window &parent)
66 {
67     dialog->set_transient_for(parent);
68     //dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
69 }
70
71 void SelectArmyDialog::run()
72 {
73     dialog->show_all();
74     int response = dialog->run();
75
76     if (response != Gtk::RESPONSE_ACCEPT)
77         selected_army = 0;
78 }
79
80 void SelectArmyDialog::on_army_toggled(Gtk::ToggleButton *toggle)
81 {
82     if (ignore_toggles)
83         return;
84     
85     selected_army = 0;
86     ignore_toggles = true;
87     for (unsigned int i = 0; i < army_toggles.size(); ++i) {
88         if (toggle == army_toggles[i])
89             selected_army = selectable[i];
90         
91         army_toggles[i]->set_active(toggle == army_toggles[i]);
92     }
93     ignore_toggles = false;
94
95     fill_in_army_info();
96     set_select_button_state();
97 }
98
99 void SelectArmyDialog::fill_in_army_toggles()
100 {
101     const Armysetlist* al = Armysetlist::getInstance();
102
103     guint32 armyset = 0;
104     if (player)
105       armyset = player->getArmyset();
106     bool pushed_back = false;
107
108     // fill in selectable armies
109     selectable.clear();
110     for (unsigned int j = 0; j < al->getSize(armyset); j++)
111     {
112         const ArmyProto *a = al->getArmy(armyset, j);
113         if (a->isHero() && d_hero_too == false)
114           continue;
115         if ((d_defends_ruins && a->getDefendsRuins()) || 
116             (!d_defends_ruins && !d_awardable))
117           {
118             pushed_back = true;
119             selectable.push_back(a);
120           }
121         if (((d_awardable && a->getAwardable()) || 
122             (!d_defends_ruins && !d_awardable)) && !pushed_back)
123           selectable.push_back(a);
124         pushed_back = false;
125     }
126
127     // fill in army options
128     army_toggles.clear();
129     toggles_table->foreach(sigc::mem_fun(toggles_table, &Gtk::Container::remove));
130     toggles_table->resize(1, 1);
131     const int no_columns = 4;
132     for (unsigned int i = 0; i < selectable.size(); ++i)
133       {
134         Gtk::ToggleButton *toggle = manage(new Gtk::ToggleButton);
135
136         Glib::RefPtr<Gdk::Pixbuf> pixbuf
137           = GraphicsCache::getInstance()->getArmyPic(armyset,
138                                                      selectable[i]->getTypeId(),
139                                                      player, NULL)->to_pixbuf();
140
141         toggle->add(*manage(new Gtk::Image(pixbuf)));
142         army_toggles.push_back(toggle);
143         int x = i % no_columns;
144         int y = i / no_columns;
145         toggles_table->attach(*toggle, x, x + 1, y, y + 1,
146                               Gtk::SHRINK, Gtk::SHRINK);
147         toggle->show_all();
148
149         toggle->signal_toggled().connect(
150                                          sigc::bind(sigc::mem_fun(this, &SelectArmyDialog::on_army_toggled),
151                                                     toggle));
152         toggle->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
153         toggle->signal_button_press_event().connect(
154                                                     sigc::bind(sigc::mem_fun(*this, &SelectArmyDialog::on_army_button_event),
155                                                                toggle), false);
156
157         toggle->signal_button_release_event().connect(
158                                                       sigc::bind(sigc::mem_fun(*this, &SelectArmyDialog::on_army_button_event),
159                                                                  toggle), false);
160       }
161
162     ignore_toggles = false;
163     if (!army_toggles.empty())
164       army_toggles[0]->set_active(true);
165 }
166
167 void SelectArmyDialog::fill_in_army_info()
168 {
169   Glib::ustring s1, s2;
170
171   if (!selected_army)
172     {
173       s1 = _("No army");
174       s1 += "\n\n\n";
175       s2 = "\n\n\n";
176     }
177   else
178     {
179       const ArmyProto *a = selected_army;
180
181       // fill in first column
182       s1 += a->getName();
183       s1 += "\n";
184       s1 += String::ucompose(_("Strength: %1"), a->getStrength());
185       s1 += "\n";
186       s1 += String::ucompose(_("Moves: %1"), a->getMaxMoves());
187
188       // fill in second column
189       s2 += "\n";
190       s2 += String::ucompose(_("Upkeep: %1"), a->getUpkeep());
191     }
192
193   army_info_label1->set_markup("<i>" + s1 + "</i>");
194   army_info_label2->set_markup("<i>" + s2 + "</i>");
195 }
196
197 void SelectArmyDialog::set_select_button_state()
198 {
199   select_button->set_sensitive(selected_army);
200 }
201
202 bool SelectArmyDialog::on_army_button_event(GdkEventButton *e, Gtk::ToggleButton *toggle)
203 {
204   MouseButtonEvent event = to_input_event(e);
205   if (event.button == MouseButtonEvent::RIGHT_BUTTON
206       && event.state == MouseButtonEvent::PRESSED) {
207     int slot = -1;
208     for (unsigned int i = 0; i < army_toggles.size(); ++i) {
209       if (toggle == army_toggles[i])
210         slot = i;
211     }
212     assert(slot != -1);
213
214     const ArmyProto *army = selectable[slot];
215
216     if (army)
217       {
218         if (army_info_tip)
219           delete army_info_tip;
220         army_info_tip = new ArmyInfoTip(toggle, army);
221       }
222     return true;
223   }
224   else if (event.button == MouseButtonEvent::RIGHT_BUTTON
225            && event.state == MouseButtonEvent::RELEASED) {
226       {
227         if (army_info_tip)
228           {
229             delete army_info_tip;
230             army_info_tip = NULL;
231           }
232       }
233     return true;
234   }
235
236   return false;
237 }