choosetech.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004  
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009  
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014  
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the 
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00018      Boston, MA  02111-1307  USA
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       // changeTechView( allTechsCheckButton->GetPressed() );
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: // A
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 

Generated on Mon May 21 01:26:30 2012 for Advanced Strategic Command by  doxygen 1.5.1