Advanced Strategic Command
choosetech.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Advanced Strategic Command; http://www.asc-hq.de
3  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  Boston, MA 02111-1307 USA
19 */
20 
21 
22 #include "choosetech.h"
23 
24 #include "../player.h"
25 #include "../gamemap.h"
26 
27 #include "../paradialog.h"
28 #include "../itemrepository.h"
29 #include "../iconrepository.h"
30 #include "../vehicletype.h"
31 #include "unitinfodialog.h"
32 
33 #include "selectionwindow.h"
34 
35 #include "pgmultilineedit.h"
36 #include "../widgets/textrenderer.h"
37 #include "../actions/directresearchcommand.h"
38 #include "../sg.h"
39 #include "../dialog.h"
40 
41 class TechWidget: public SelectionWidget {
42  const Technology* tech;
43  static Surface clippingSurface;
44  Surface& getClippingSurface() { return clippingSurface; };
45  int actplayer;
46  static const int widgetHeight = 60;
47  bool info();
48  public:
49  TechWidget( PG_Widget* parent, const PG_Point& pos, int width, const Technology* technology, int player = 0 );
50  ASCString getName() const;
51  const Technology* getTechnology() const { return tech; };
52  protected:
53  void display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst );
54 };
55 
56 TechWidget :: TechWidget( PG_Widget* parent, const PG_Point& pos, int width, const Technology* technology, int player ) : SelectionWidget( parent, PG_Rect( pos.x, pos.y, width, widgetHeight )), tech( technology ), actplayer(player)
57 {
58 
59  int lineheight = 20;
60 
61  int xoffs = 20;
62  if ( tech->relatedUnitID > 0 )
63  xoffs += 40;
64 
65  int www = width - xoffs - 20 - 2 * lineheight;
66 
67  new PG_Label( this, PG_Rect( xoffs, 10, www, 25 ), tech->name );
68  new PG_Label( this, PG_Rect( xoffs, 30, www, 25 ), ASCString::toString( tech->researchpoints) + " RP" );
69 
70  if ( tech->relatedUnitID > 0 ) {
71  PG_Button* b = new PG_Button( this, PG_Rect( width - 2 * lineheight - 10, Height()/2-lineheight, 2*lineheight, 2*lineheight ));
72  b->SetIcon( IconRepository::getIcon( "blue-i.png").getBaseSurface() );
73  b->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &TechWidget::info )));
74  }
75 
76  SetTransparency( 255 );
77 };
78 
79 bool TechWidget::info()
80 {
81  const VehicleType* vt = vehicleTypeRepository.getObject_byID( tech->relatedUnitID );
82  if ( vt )
83  unitInfoDialog( vt );
84  return true;
85 }
86 
87 
88 
90 {
91  return tech->name;
92 };
93 
94 void TechWidget::display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst )
95 {
96  VehicleType* vt = NULL;
97  if ( tech->relatedUnitID > 0 )
98  if ( (vt = vehicleTypeRepository.getObject_byID( tech->relatedUnitID ))) {
99  if ( !getClippingSurface().valid() )
100  getClippingSurface() = Surface::createSurface( fieldsizex + 10, fieldsizey + 10, 32, 0 );
101 
102  getClippingSurface().Fill(0);
103 
104  vt->paint( getClippingSurface(), SPoint(5,5) );
105  PG_Draw::BlitSurface( getClippingSurface().getBaseSurface(), src, surface, dst);
106  }
107 }
108 
109 Surface TechWidget::clippingSurface;
110 
111 
112 
113 
114 
115  class TechnologySelectionItemFactory: public SelectionItemFactory, public sigc::trackable {
116  Player& player;
117  bool allTechs;
118  public:
119  typedef vector<const Technology*> Container;
120 
121  protected:
122  Container::iterator it;
124 
125  public:
127 
128 
129  bool showAllTechs( bool all) { allTechs = all; return true; };
130 
131  void restart();
132  sigc::signal<void,const Technology*> techSelected;
133 
134  SelectionWidget* spawnNextItem( PG_Widget* parent, const PG_Point& pos );
135 
136  void itemSelected( const SelectionWidget* widget, bool mouse );
137  };
138 
139 
140 
141  TechnologySelectionItemFactory :: TechnologySelectionItemFactory( Player& theplayer ) : player(theplayer), allTechs(false)
142  {
143  restart();
144  };
145 
146  bool techComp ( const Technology* t1, const Technology* t2 )
147  {
148  return (t1->relatedUnitID > 0 && t2->relatedUnitID < 0 ) ||
149  (t1->techlevel < t2->techlevel) ||
150  (t1->techlevel == t2->techlevel && t1->name < t2->name );
151  }
152 
154  {
155  DirectResearchCommand drc( player );
156  items = drc.getAvailableTechnologies( allTechs );
157 
158  sort( items.begin(), items.end(), techComp );
159  it = items.begin();
160  };
161 
162 
163  SelectionWidget* TechnologySelectionItemFactory::spawnNextItem( PG_Widget* parent, const PG_Point& pos )
164  {
165  if ( it != items.end() ) {
166  const Technology* v = *(it++);
167 
168  return new TechWidget( parent, pos, parent->Width() - 15, v, player.getPosition() );
169  } else
170  return NULL;
171  };
172 
173 
175  {
176  if ( !widget )
177  return;
178 
179  const TechWidget* tw = dynamic_cast<const TechWidget*>(widget);
180  assert( tw );
181 
183  }
184 
185 
186 
187 class ChooseTech : public ASC_PG_Dialog
188 {
189  ItemSelectorWidget* itemSelector;
191  PG_MultiLineEdit* techList;
192  Player& player;
193  PG_CheckButton* allTechsCheckButton;
194 
195  PG_Label* pointsLabel;
196  PG_Label* availLabel;
197  const Technology* goal;
198  bool okPressed;
199 
200  bool changeTechView( bool all )
201  {
202  factory->showAllTechs ( all );
203  itemSelector->reLoad( true );
204  return true;
205 
206  }
207 
208  void toggleAllTechButton()
209  {
210  if ( allTechsCheckButton->GetPressed() )
211  allTechsCheckButton->SetUnpressed();
212  else
213  allTechsCheckButton->SetPressed();
214  // changeTechView( allTechsCheckButton->GetPressed() );
215  }
216 
217 
218  void techSelected( const Technology* tech )
219  {
220  ASCString s;
221  list<const Technology*> techs;
222  if ( !tech->eventually_available( player.research , &techs )) {
223  warningMessage("Inconsistency in ChooseTech::techSelected");
224  return;
225  }
226 
227  assert( techs.begin() != techs.end() );
228 
229  int points = 0;
230  for ( list<const Technology*>::iterator i = techs.begin(); i != techs.end(); ++i ) {
231  s += (*i)->name + "\n";
232  points += (*i)->researchpoints;
233  }
234  techList->SetText( s );
235 
236  pointsLabel->SetText( ASCString("Sum: ") + ASCString::toString(points) + " Points" );
237 
238  goal = tech;
239  };
240 
241  protected:
242  bool handleButtonClick(PG_Button* button)
243  {
244  if ( goal )
245  return ASC_PG_Dialog::handleButtonClick( button );
246  else
247  return false;
248  };
249 
250  bool ok()
251  {
252  if ( goal || !itemSelector->getItemNum() ) {
253 
254  if ( goal ) {
255  auto_ptr<DirectResearchCommand> drc ( new DirectResearchCommand( player ));
256  drc->setTechnology( goal );
257  ActionResult res = drc->execute( createContext( player.getParentMap() ));
258  if ( res.successful() ) {
259  drc.release();
260  okPressed = true;
261  QuitModal();
262  } else
263  displayActionError( res);
264  } else
265  QuitModal();
266  return true;
267  } else
268  return false;
269  }
270 
271  bool cancel()
272  {
273  player.research.goal = NULL;
274  player.research.activetechnology = NULL;
275  QuitModal();
276  return true;
277  }
278 
280  {
281  if ( goal ) {
282  ASCString msg = "Prerequisites for Technology " + goal->name + ":\n";
283  msg += goal->techDependency.showDebug( player.research );
284  ViewFormattedText vft("Technology Prerequisites", msg, PG_Rect( -1, -1, 500, 400 ));
285  vft.Show();
286  vft.RunModal();
287  }
288  return true;
289  }
290 
291  bool eventKeyDown(const SDL_KeyboardEvent* key)
292  {
293  int mod = SDL_GetModState() & ~(KMOD_NUM | KMOD_CAPS | KMOD_MODE);
294 
295  if ( !mod )
296  if ( key->keysym.sym == SDLK_RETURN )
297  return ok();
298 
299 
300  if ( mod & KMOD_CTRL ) {
301  switch ( key->keysym.unicode ) {
302  case 1: // A
303  toggleAllTechButton();
304  return true;
305  };
306  }
307 
308  return false;
309  };
310 
311 
312  public:
313  ChooseTech( Player& my_player ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 770, 600), "Choose Technology" ) , factory(NULL), player( my_player ), goal(NULL), okPressed(false)
314  {
315  factory = new TechnologySelectionItemFactory( player );
316  factory->techSelected.connect( sigc::mem_fun( *this, &ChooseTech::techSelected ));
317  itemSelector = new ItemSelectorWidget( this, PG_Rect( 10, 40, 400, Height() - 80 ), factory );
318 
319  (allTechsCheckButton = new PG_CheckButton( this, PG_Rect( 10, Height() - 40, 300, 25 ), "Show ~A~ll Technologies"))->sigClick.connect( sigc::mem_fun( *this, &ChooseTech::changeTechView));
320  techList = new PG_MultiLineEdit( this, PG_Rect ( 450, 40, 300, 200 ));
321  techList->SetEditable(false);
322  pointsLabel = new PG_Label( this, PG_Rect( 450, 250, 300, 25 ));
323  availLabel = new PG_Label( this, PG_Rect( 450, 280, 300, 25 ), "Accumulated research points: " + ASCString::toString( player.research.progress) );
324 
325  (new PG_Button( this, PG_Rect( 450, 320, 300, 20), "List Prerequisites" ))->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &ChooseTech::showPrerequisites )));
326 
327  AddStandardButton("~C~ancel")->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &ChooseTech::cancel )));
328  AddStandardButton("~O~K")->sigClick.connect( sigc::hide( sigc::mem_fun( *this, &ChooseTech::ok )));
329  };
330 
332  {
333  return okPressed;
334  }
335 
336 };
337 
338 
339 
340 
342 {
343  ChooseTech ct( player);
344  ct.Show();
345  ct.RunModal();
346  return ct.selectionPerformed();
347 }
348 
349 
void reLoad(bool show=false)
int relatedUnitID
Definition: research.h:139
vector< const Technology * > getAvailableTechnologies(bool longTerm)
returns the technologies that can be researched by the player
vector< const Technology * > Container
Definition: choosetech.cpp:119
bool techComp(const Technology *t1, const Technology *t2)
Definition: choosetech.cpp:146
ASCString showDebug(const Research &research) const
Definition: research.cpp:331
int getPosition() const
Definition: player.h:112
const GameMap * getParentMap() const
Definition: player.h:114
Context createContext(GameMap *gamemap)
bool eventually_available(const Research &res, list< const Technology * > *dependencies) const
Definition: research.cpp:574
const Technology * getTechnology() const
Definition: choosetech.cpp:51
bool showPrerequisites()
Definition: choosetech.cpp:279
void warningMessage(const ASCString &str)
static Surface createSurface(int width, int height, SDLmm::Color color=255)
Definition: surface.cpp:387
ASCString getName() const
Definition: choosetech.cpp:89
SelectionWidget * spawnNextItem(PG_Widget *parent, const PG_Point &pos)
Definition: choosetech.cpp:163
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
bool chooseSingleTechnology(Player &player)
lets the player choose an available technology
Definition: choosetech.cpp:341
ChooseTech(Player &my_player)
Definition: choosetech.cpp:313
#define fieldsizey
Definition: typen.h:441
The class describing properties that are common to all vehicles of a certain kind.
Definition: vehicletype.h:177
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
TechDependency techDependency
Definition: research.h:143
ItemRepositoryLoader< VehicleType > vehicleTypeRepository("vehicletype")
int getItemNum() const
bool handleButtonClick(PG_Button *button)
Definition: choosetech.cpp:242
const Technology * activetechnology
the technology that is currently being researched
Definition: research.h:191
Adapter class for using Paragui Dialogs in ASC. This class transfers the event control from ASC to Pa...
Definition: paradialog.h:127
const Technology * goal
the technology that is defined as long-term goal
Definition: research.h:194
cancels the research on the current technology, losing all research points
#define fieldsizex
Definition: typen.h:440
bool successful() const
void display(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
Definition: choosetech.cpp:94
void itemSelected(const SelectionWidget *widget, bool mouse)
Definition: choosetech.cpp:174
SDLmm::SPoint SPoint
Definition: surface.h:27
Research research
the status of the scientific research
Definition: player.h:142
int techlevel
Definition: research.h:138
static Surface & getIcon(const ASCString &name)
ASCString name
Definition: research.h:137
void paint(Surface &s, SPoint pos, const PlayerColor &player, int direction=0) const
bool eventKeyDown(const SDL_KeyboardEvent *key)
Definition: choosetech.cpp:291
TechnologySelectionItemFactory(Player &player)
Definition: choosetech.cpp:141
int researchpoints
Definition: research.h:135
the different players in ASC. There may be 8 players (0..7) and neutral units (8) ...
Definition: player.h:99
void displayActionError(const ActionResult &result, const ASCString &additionalInfo)
Definition: dialog.cpp:2168
bool cancel()
Definition: choosetech.cpp:271
bool selectionPerformed()
Definition: choosetech.cpp:331
PG_Button * AddStandardButton(const ASCString &name)
Definition: paradialog.cpp:516
TechWidget(PG_Widget *parent, const PG_Point &pos, int width, const Technology *technology, int player=0)
Definition: choosetech.cpp:56
void unitInfoDialog(const VehicleType *vt)
int progress
Definition: research.h:189
sigc::signal< void, const Technology * > techSelected
Definition: choosetech.cpp:132