00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "choosetech.h"
00023
00024 #include "../player.h"
00025 #include "../gamemap.h"
00026
00027 #include "../paradialog.h"
00028 #include "../itemrepository.h"
00029 #include "../iconrepository.h"
00030 #include "../vehicletype.h"
00031 #include "unitinfodialog.h"
00032
00033 #include "selectionwindow.h"
00034
00035 #include "pgmultilineedit.h"
00036 #include "../widgets/textrenderer.h"
00037 #include "../actions/directresearchcommand.h"
00038 #include "../sg.h"
00039 #include "../dialog.h"
00040
00041 class TechWidget: public SelectionWidget {
00042 const Technology* tech;
00043 static Surface clippingSurface;
00044 Surface& getClippingSurface() { return clippingSurface; };
00045 int actplayer;
00046 static const int widgetHeight = 60;
00047 bool info();
00048 public:
00049 TechWidget( PG_Widget* parent, const PG_Point& pos, int width, const Technology* technology, int player = 0 );
00050 ASCString getName() const;
00051 const Technology* getTechnology() const { return tech; };
00052 protected:
00053 void display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst );
00054 };
00055
00056 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)
00057 {
00058
00059 int lineheight = 20;
00060
00061 int xoffs = 20;
00062 if ( tech->relatedUnitID > 0 )
00063 xoffs += 40;
00064
00065 int www = width - xoffs - 20 - 2 * lineheight;
00066
00067 new PG_Label( this, PG_Rect( xoffs, 10, www, 25 ), tech->name );
00068 new PG_Label( this, PG_Rect( xoffs, 30, www, 25 ), ASCString::toString( tech->researchpoints) + " RP" );
00069
00070 if ( tech->relatedUnitID > 0 ) {
00071 PG_Button* b = new PG_Button( this, PG_Rect( width - 2 * lineheight - 10, Height()/2-lineheight, 2*lineheight, 2*lineheight ));
00072 b->SetIcon( IconRepository::getIcon( "blue-i.png").getBaseSurface() );
00073 b->sigClick.connect( SigC::slot( *this, &TechWidget::info ));
00074 }
00075
00076 SetTransparency( 255 );
00077 };
00078
00079 bool TechWidget::info()
00080 {
00081 const VehicleType* vt = vehicleTypeRepository.getObject_byID( tech->relatedUnitID );
00082 if ( vt )
00083 unitInfoDialog( vt );
00084 return true;
00085 }
00086
00087
00088
00089 ASCString TechWidget::getName() const
00090 {
00091 return tech->name;
00092 };
00093
00094 void TechWidget::display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst )
00095 {
00096 VehicleType* vt = NULL;
00097 if ( tech->relatedUnitID > 0 )
00098 if ( (vt = vehicleTypeRepository.getObject_byID( tech->relatedUnitID ))) {
00099 if ( !getClippingSurface().valid() )
00100 getClippingSurface() = Surface::createSurface( fieldsizex + 10, fieldsizey + 10, 32, 0 );
00101
00102 getClippingSurface().Fill(0);
00103
00104 vt->paint( getClippingSurface(), SPoint(5,5) );
00105 PG_Draw::BlitSurface( getClippingSurface().getBaseSurface(), src, surface, dst);
00106 }
00107 }
00108
00109 Surface TechWidget::clippingSurface;
00110
00111
00112
00113
00114
00115 class TechnologySelectionItemFactory: public SelectionItemFactory, public SigC::Object {
00116 Player& player;
00117 bool allTechs;
00118 public:
00119 typedef vector<const Technology*> Container;
00120
00121 protected:
00122 Container::iterator it;
00123 Container items;
00124
00125 public:
00126 TechnologySelectionItemFactory( Player& player );
00127
00128
00129 bool showAllTechs( bool all) { allTechs = all; return true; };
00130
00131 void restart();
00132 SigC::Signal1<void,const Technology*> techSelected;
00133
00134 SelectionWidget* spawnNextItem( PG_Widget* parent, const PG_Point& pos );
00135
00136 void itemSelected( const SelectionWidget* widget, bool mouse );
00137 };
00138
00139
00140
00141 TechnologySelectionItemFactory :: TechnologySelectionItemFactory( Player& theplayer ) : player(theplayer), allTechs(false)
00142 {
00143 restart();
00144 };
00145
00146 bool techComp ( const Technology* t1, const Technology* t2 )
00147 {
00148 return (t1->relatedUnitID > 0 && t2->relatedUnitID < 0 ) ||
00149 (t1->techlevel < t2->techlevel) ||
00150 (t1->techlevel == t2->techlevel && t1->name < t2->name );
00151 }
00152
00153 void TechnologySelectionItemFactory::restart()
00154 {
00155 DirectResearchCommand drc( player );
00156 items = drc.getAvailableTechnologies( allTechs );
00157
00158 sort( items.begin(), items.end(), techComp );
00159 it = items.begin();
00160 };
00161
00162
00163 SelectionWidget* TechnologySelectionItemFactory::spawnNextItem( PG_Widget* parent, const PG_Point& pos )
00164 {
00165 if ( it != items.end() ) {
00166 const Technology* v = *(it++);
00167
00168 return new TechWidget( parent, pos, parent->Width() - 15, v, player.getPosition() );
00169 } else
00170 return NULL;
00171 };
00172
00173
00174 void TechnologySelectionItemFactory::itemSelected( const SelectionWidget* widget, bool mouse )
00175 {
00176 if ( !widget )
00177 return;
00178
00179 const TechWidget* tw = dynamic_cast<const TechWidget*>(widget);
00180 assert( tw );
00181
00182 techSelected(tw->getTechnology());
00183 }
00184
00185
00186
00187 class ChooseTech : public ASC_PG_Dialog
00188 {
00189 ItemSelectorWidget* itemSelector;
00190 TechnologySelectionItemFactory* factory;
00191 PG_MultiLineEdit* techList;
00192 Player& player;
00193 PG_CheckButton* allTechsCheckButton;
00194
00195 PG_Label* pointsLabel;
00196 PG_Label* availLabel;
00197 const Technology* goal;
00198 bool okPressed;
00199
00200 bool changeTechView( bool all )
00201 {
00202 factory->showAllTechs ( all );
00203 itemSelector->reLoad( true );
00204 return true;
00205
00206 }
00207
00208 void toggleAllTechButton()
00209 {
00210 if ( allTechsCheckButton->GetPressed() )
00211 allTechsCheckButton->SetUnpressed();
00212 else
00213 allTechsCheckButton->SetPressed();
00214
00215 }
00216
00217
00218 void techSelected( const Technology* tech )
00219 {
00220 ASCString s;
00221 list<const Technology*> techs;
00222 if ( !tech->eventually_available( player.research , &techs )) {
00223 warningMessage("Inconsistency in ChooseTech::techSelected");
00224 return;
00225 }
00226
00227 assert( techs.begin() != techs.end() );
00228
00229 int points = 0;
00230 for ( list<const Technology*>::iterator i = techs.begin(); i != techs.end(); ++i ) {
00231 s += (*i)->name + "\n";
00232 points += (*i)->researchpoints;
00233 }
00234 techList->SetText( s );
00235
00236 pointsLabel->SetText( ASCString("Sum: ") + ASCString::toString(points) + " Points" );
00237
00238 goal = tech;
00239 };
00240
00241 protected:
00242 bool handleButtonClick(PG_Button* button)
00243 {
00244 if ( goal )
00245 return ASC_PG_Dialog::handleButtonClick( button );
00246 else
00247 return false;
00248 };
00249
00250 bool ok()
00251 {
00252 if ( goal || !itemSelector->getItemNum() ) {
00253
00254 if ( goal ) {
00255 auto_ptr<DirectResearchCommand> drc ( new DirectResearchCommand( player ));
00256 drc->setTechnology( goal );
00257 ActionResult res = drc->execute( createContext( player.getParentMap() ));
00258 if ( res.successful() ) {
00259 drc.release();
00260 okPressed = true;
00261 QuitModal();
00262 } else
00263 displayActionError( res);
00264 } else
00265 QuitModal();
00266 return true;
00267 } else
00268 return false;
00269 }
00270
00271 bool cancel()
00272 {
00273 player.research.goal = NULL;
00274 player.research.activetechnology = NULL;
00275 QuitModal();
00276 return true;
00277 }
00278
00279 bool showPrerequisites()
00280 {
00281 if ( goal ) {
00282 ASCString msg = "Prerequisites for Technology " + goal->name + ":\n";
00283 msg += goal->techDependency.showDebug( player.research );
00284 ViewFormattedText vft("Technology Prerequisites", msg, PG_Rect( -1, -1, 500, 400 ));
00285 vft.Show();
00286 vft.RunModal();
00287 }
00288 return true;
00289 }
00290
00291 bool eventKeyDown(const SDL_KeyboardEvent* key)
00292 {
00293 int mod = SDL_GetModState() & ~(KMOD_NUM | KMOD_CAPS | KMOD_MODE);
00294
00295 if ( !mod )
00296 if ( key->keysym.sym == SDLK_RETURN )
00297 return ok();
00298
00299
00300 if ( mod & KMOD_CTRL ) {
00301 switch ( key->keysym.unicode ) {
00302 case 1:
00303 toggleAllTechButton();
00304 return true;
00305 };
00306 }
00307
00308 return false;
00309 };
00310
00311
00312 public:
00313 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)
00314 {
00315 factory = new TechnologySelectionItemFactory( player );
00316 factory->techSelected.connect( SigC::slot( *this, &ChooseTech::techSelected ));
00317 itemSelector = new ItemSelectorWidget( this, PG_Rect( 10, 40, 400, Height() - 80 ), factory );
00318
00319 (allTechsCheckButton = new PG_CheckButton( this, PG_Rect( 10, Height() - 40, 300, 25 ), "Show ~A~ll Technologies"))->sigClick.connect( SigC::slot( *this, &ChooseTech::changeTechView));
00320 techList = new PG_MultiLineEdit( this, PG_Rect ( 450, 40, 300, 200 ));
00321 techList->SetEditable(false);
00322 pointsLabel = new PG_Label( this, PG_Rect( 450, 250, 300, 25 ));
00323 availLabel = new PG_Label( this, PG_Rect( 450, 280, 300, 25 ), "Accumulated research points: " + ASCString::toString( player.research.progress) );
00324
00325 (new PG_Button( this, PG_Rect( 450, 320, 300, 20), "List Prerequisites" ))->sigClick.connect( SigC::slot( *this, &ChooseTech::showPrerequisites ));
00326
00327 AddStandardButton("~C~ancel")->sigClick.connect( SigC::slot( *this, &ChooseTech::cancel ));
00328 AddStandardButton("~O~K")->sigClick.connect( SigC::slot( *this, &ChooseTech::ok ));
00329 };
00330
00331 bool selectionPerformed()
00332 {
00333 return okPressed;
00334 }
00335
00336 };
00337
00338
00339
00340
00341 bool chooseSingleTechnology( Player& player )
00342 {
00343 ChooseTech ct( player);
00344 ct.Show();
00345 ct.RunModal();
00346 return ct.selectionPerformed();
00347 }
00348
00349