cargodialog.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           cargodialog.cpp  -  description
00003                              -------------------
00004     begin                : Tue Oct 24 2000
00005     copyright            : (C) 2000 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <pgimage.h>
00019 #include <pgtooltiphelp.h>
00020 #include "cargodialog.h"
00021 #include "cargowidget.h"
00022 #include "vehicletypeselector.h"
00023 
00024 #include "../containerbase.h"
00025 #include "../paradialog.h"
00026 #include "../util/messaginghub.h"
00027 #include "../iconrepository.h"
00028 #include "../vehicle.h"
00029 #include "../gamemap.h"
00030 #include "../containercontrols.h"
00031 
00032 #include "../asc-mainscreen.h"
00033 #include "../guiiconhandler.h"
00034 #include "../guifunctions.h"
00035 #include "../guifunctions-interface.h"
00036 #include "../cannedmessages.h"
00037 #include "../dashboard.h"
00038 #include "../dialog.h"
00039 #include "../containerbase-functions.h"
00040 #include "../resourcenet.h"
00041 
00042 #include "../containerbase-functions.h"
00043 #include "../gameoptions.h"
00044 
00045 #include "../actions/moveunitcommand.h"
00046 #include "../actions/cargomovecommand.h"
00047 #include "../actions/servicecommand.h"
00048 #include "../actions/recycleunitcommand.h"
00049 #include "../actions/repairunitcommand.h"
00050 #include "../actions/trainunitcommand.h"
00051 #include "../actions/repairbuildingcommand.h"
00052 #include "../actions/transfercontrolcommand.h"
00053 #include "../actions/setresourceprocessingratecommand.h"
00054 
00055 #include "selectionwindow.h"
00056 #include "ammotransferdialog.h"
00057 #include "unitinfodialog.h"
00058 #include "vehicleproductionselection.h"
00059 #include "../sg.h"
00060 #include "../spfst.h"
00061 
00062 const VehicleType* selectVehicletype( ContainerBase* plant, const vector<VehicleType*>& items );
00063 
00064 
00065 class CargoDialog;
00066 
00067 class SubWindow: public SigC::Object
00068 {
00069    protected:
00070       CargoDialog* cargoDialog;
00071       PG_Widget* widget;
00072 
00073       SubWindow() : cargoDialog(NULL), widget(NULL) {};
00074       ContainerBase* container();
00075    public:
00076       virtual bool available( CargoDialog* cd ) = 0;
00077       virtual ASCString getASCTXTname() = 0;
00078       virtual ASCString getFullName() = 0;
00079       virtual void registerSubwindow( CargoDialog* cd );
00080       virtual void registerChilds( CargoDialog* cd );
00081       virtual void update() = 0;
00082       virtual ~SubWindow() {} ;
00083 };
00084 
00085 
00086 class SubWinButton : public PG_Button
00087 {
00088 
00089       static int calcWidth() {
00090          if ( buttonwidth == -1 ) {
00091             buttonwidth = IconRepository::getIcon("cargo-buttonpressed.png").w();
00092          }
00093          return buttonwidth;
00094       }
00095 
00096       static int calcHeight() {
00097          if ( buttonheight == -1 ) {
00098             buttonheight = IconRepository::getIcon("cargo-buttonpressed.png").h();
00099          }
00100          return buttonheight;
00101       }
00102 
00103    public:
00104       static int buttonwidth;
00105       static int buttonheight;
00106 
00107 
00108       SubWinButton( PG_Widget *parent, const SPoint& pos, SubWindow* subWindow ) : PG_Button( parent, PG_Rect( pos.x, pos.y, calcWidth(), calcHeight() ), "", -1, "SubWinButton") {
00109          SetBackground( PRESSED, IconRepository::getIcon("cargo-buttonpressed.png").getBaseSurface() );
00110          SetBackground( HIGHLITED, IconRepository::getIcon("cargo-buttonhighlighted.png").getBaseSurface() );
00111          SetBackground( UNPRESSED, IconRepository::getIcon("cargo-buttonunpressed.png").getBaseSurface() );
00112          SetBorderSize(0,0,0);
00113          ASCString filename = ASCString("cargo-") + subWindow->getASCTXTname();
00114          SetIcon( IconRepository::getIcon( filename + ".png" ).getBaseSurface(),
00115                   IconRepository::getIcon( filename + "-pressed.png" ).getBaseSurface(),
00116                   IconRepository::getIcon( filename + ".png" ).getBaseSurface() );
00117          SetToggle( true );
00118          new PG_ToolTipHelp ( this, subWindow->getFullName() );
00119       };
00120 };
00121 
00122 int SubWinButton::buttonwidth = -1;
00123 int SubWinButton::buttonheight = -1;
00124 
00125 
00126 
00127 namespace CargoGuiFunctions
00128 {
00129 
00130 class MovementDestination : public GuiFunctions::Movement
00131 {
00132       PG_Widget& parent;
00133    public:
00134       MovementDestination( PG_Widget& masterParent ) : parent( masterParent)  {};
00135 
00136       void execute( const MapCoordinate& pos, ContainerBase* subject, int num ) {
00137          GuiFunctions::Movement::execute( pos, subject, num );
00138          if ( !NewGuiHost::pendingCommand )
00139             parent.QuitModal();
00140       }
00141 };
00142 
00143 class CancelMovement : public GuiFunctions::Cancel
00144 {
00145       PG_Widget& parent;
00146    public:
00147       CancelMovement ( PG_Widget& masterParent ) : parent( masterParent)  {};
00148 
00149       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00150       {
00151          if ( !NewGuiHost::pendingCommand )
00152             parent.QuitModal();
00153          
00154          return true;
00155       }
00156 
00157       void execute( const MapCoordinate& pos, ContainerBase* subject, int num ) {
00158          GuiFunctions::Cancel::execute( pos, subject, num );
00159          parent.QuitModal();
00160       }
00161 };
00162 
00163 
00164 class CloseDialog : public GuiFunction
00165 {
00166       CargoDialog& parent;
00167    public:
00168       CloseDialog( CargoDialog& masterParent ) : parent( masterParent)  {};
00169       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00170       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00171       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00172       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00173       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00174 };
00175 
00176 
00177 class Movement : public GuiFunction
00178 {
00179       CargoDialog& parent;
00180    public:
00181       Movement( CargoDialog& masterParent ) : parent( masterParent)  {};
00182       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00183       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00184       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00185       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00186       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00187 };
00188 
00189 
00190 class UnitProduction : public GuiFunction, public SigC::Object
00191 {
00192       CargoDialog& parent;
00193       ConstructUnitCommand::Producables producables;
00194       ConstructUnitCommand* constructUnitCommand;
00195       void productionLinesChanged();
00196    public:
00197       UnitProduction( CargoDialog& masterParent ) : parent( masterParent), constructUnitCommand(NULL)  {};
00198       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00199       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00200       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00201       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00202       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00203 };
00204 
00205 class UnitTraining : public GuiFunction
00206 {
00207       CargoDialog& parent;
00208    public:
00209       UnitTraining( CargoDialog& masterParent ) : parent( masterParent)  {};
00210       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00211       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00212       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00213       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00214       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00215 };
00216 
00217 class RefuelUnitCommand : public GuiFunction
00218 {
00219       CargoDialog& parent;
00220    public:
00221       RefuelUnitCommand( CargoDialog& masterParent ) : parent( masterParent)  {};
00222       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00223       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00224       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00225       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00226       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00227 };
00228 class RefuelUnitDialogCommand : public GuiFunction
00229 {
00230       CargoDialog& parent;
00231    public:
00232       RefuelUnitDialogCommand( CargoDialog& masterParent ) : parent( masterParent)  {};
00233       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00234       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00235       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00236       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00237       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00238 };
00239 
00240 class RepairUnit : public GuiFunction
00241 {
00242       CargoDialog& parent;
00243    public:
00244       RepairUnit( CargoDialog& masterParent ) : parent( masterParent)  {};
00245       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00246       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00247       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00248       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00249       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00250 };
00251 
00252 class MoveUnitUp : public GuiFunction
00253 {
00254       CargoDialog& parent;
00255    public:
00256       MoveUnitUp ( CargoDialog& masterParent ) : parent( masterParent)  {};
00257       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00258       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00259       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00260       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00261       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00262 };
00263 
00264 class MoveUnitIntoInnerContainer : public GuiFunction
00265 {
00266       CargoDialog& parent;
00267    public:
00268       MoveUnitIntoInnerContainer ( CargoDialog& masterParent ) : parent( masterParent)  {};
00269       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00270       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00271       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00272       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00273       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00274 };
00275 
00276 
00277 class OpenContainer: public GuiFunction
00278 {
00279       CargoDialog& parent;
00280    public:
00281       OpenContainer( CargoDialog& masterParent ) : parent( masterParent)  {};
00282       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00283       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00284       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00285       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00286       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00287 };
00288 
00289 class RecycleUnitCommandButton : public GuiFunction
00290 {
00291       ASCString getCommandName( const ContainerBase* carrier );
00292       CargoDialog& parent;
00293    public:
00294       RecycleUnitCommandButton( CargoDialog& masterParent ) : parent( masterParent)  {};
00295       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00296       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00297       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00298       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00299       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00300 };
00301 
00302 
00303 class UnitInfo : public GuiFunction
00304 {
00305       CargoDialog& parent;
00306    public:
00307       UnitInfo( CargoDialog& masterParent ) : parent( masterParent)  {};
00308       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00309       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00310       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num );
00311       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00312       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00313 };
00314 
00315 class TransferUnitControl : public GuiFunction
00316 {
00317       CargoDialog& parent;
00318    public:
00319       TransferUnitControl( CargoDialog& masterParent ) : parent( masterParent)  {};
00320       bool available( const MapCoordinate& pos, ContainerBase* subject, int num );
00321       void execute( const MapCoordinate& pos, ContainerBase* subject, int num );
00322       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num );
00323       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num );
00324 };
00325 
00326 
00327 
00328 }; // namespace CargoGuiFunctions
00329 
00330 
00331 class BuildingControlWindow;
00332 class CargoInfoWindow;
00333 
00334 class CargoDialog : public Panel
00335 {
00336 
00337       GuiIconHandler guiIconHandler;
00338 
00339       ContainerBase* container;
00340       bool setupOK;
00341       Surface infoImage;
00342 
00343       typedef vector<SubWindow*> Activesubwindows;
00344       Activesubwindows activesubwindows;
00345 
00346       typedef deallocating_vector<SubWindow*> Subwindows;
00347       Subwindows subwindows;
00348 
00349       vector<SubWinButton*> subWinButtons;
00350 
00351       CargoWidget* cargoWidget;
00352       SubWindow* researchWindow;
00353       SubWindow* matterWindow;
00354       BuildingControlWindow* buildingControlWindow;
00355 
00356       bool shutdownImmediately;
00357 
00358       void containerDestroyed() {
00359          shutdownImmediately = true;
00360       }
00361 
00362       CargoInfoWindow* ciw;
00363 
00364       bool eventKeyDown(const SDL_KeyboardEvent* key) {
00365          int mod = SDL_GetModState() & ~(KMOD_NUM | KMOD_CAPS | KMOD_MODE);
00366 
00367          if ( !mod  ) {
00368             if ( key->keysym.sym == SDLK_ESCAPE ) {
00369                QuitModal();
00370                return true;
00371             }
00372          }
00373 
00374          if ( (mod & KMOD_SHIFT) && (mod & KMOD_CTRL)) {
00375             switch ( key->keysym.unicode ) {
00376                case 26: // Z
00377                   getContainer()->getMap()->actions.redo( createContext( getContainer()->getMap() ) );
00378                   cargoChanged();
00379                   return true;
00380             }
00381          }
00382 
00383          if ( (mod & KMOD_CTRL) &&  !(mod & KMOD_SHIFT)) {
00384             switch ( key->keysym.unicode ) {
00385                case 26: // Z
00386                   getContainer()->getMap()->actions.undo( createContext( getContainer()->getMap() ) );
00387                   if ( shutdownImmediately ) {
00388                      QuitModal();
00389                      return true;
00390                   }
00391 
00392                   cargoChanged();
00393                   for ( Activesubwindows::iterator i =  activesubwindows.begin(); i != activesubwindows.end(); ++i )
00394                      (*i)->update();
00395                   return true;
00396             }
00397          }
00398 
00399          return false;
00400       };
00401 
00402 
00403 
00404       void registerSpecialDisplay( const ASCString& name ) {
00405          SpecialDisplayWidget* sdw = dynamic_cast<SpecialDisplayWidget*>( FindChild( name, true ) );
00406          if ( sdw )
00407             sdw->display.connect( SigC::slot( *this, &CargoDialog::painter ));
00408       };
00409 
00410       void registerSpecialInput( const ASCString& name ) {
00411          SpecialInputWidget* siw = dynamic_cast<SpecialInputWidget*>( FindChild( name, true ) );
00412          if ( siw )
00413             siw->sigMouseButtonDown.connect( SigC::slot( *this, &CargoDialog::onClick ));
00414       };
00415 
00416       bool onClick ( PG_MessageObject* obj, const SDL_MouseButtonEvent* event ) {
00417          PG_Widget* w = dynamic_cast<PG_Widget*>(obj);
00418          if ( w ) {
00419             // click( w->GetName() );
00420             return true;
00421          }
00422          return false;
00423       };
00424 
00425       void onUnitClick ( Vehicle* veh,SPoint pos, bool first ) {
00426          // if ( veh )
00427          if ( mainScreenWidget&& mainScreenWidget->getGuiHost() && (!first || CGameOptions::Instance()->mouse.singleClickAction) ) {
00428             SPoint iconPos = pos;
00429             if ( veh ) {
00430                iconPos.x -= smallGuiIconSizeX/2;
00431                iconPos.y -= smallGuiIconSizeY/2;
00432             } else {
00433                iconPos.x += 2;
00434                iconPos.y += 2;
00435             }
00436 
00437             mainScreenWidget->getGuiHost()->showSmallIcons( this, iconPos, false );
00438          }
00439 
00440       };
00441 
00442       void clearSmallIcons( ) {
00443          if ( mainScreenWidget && mainScreenWidget->getGuiHost() )
00444             mainScreenWidget->getGuiHost()->clearSmallIcons();
00445       }
00446 
00447 
00448 
00449       void painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst) {
00450          Surface screen = Surface::Wrap( PG_Application::GetScreen() );
00451 
00452          if ( name == "unitpad_unitsymbol" ) {
00453             Vehicle* v = dynamic_cast<Vehicle*>(container);
00454             if ( v )
00455                v->paint( screen, SPoint( dst.x, dst.y ), 0);
00456          }
00457          
00458          if ( name == "SelectedImage" ) {
00459             if ( getMarkedUnit() )
00460                getMarkedUnit()->typ->paint( screen, SPoint( dst.x, dst.y ), getMarkedUnit()->getOwningPlayer().getPlayerColor() );
00461          }
00462          
00463       };
00464 
00465       bool activate_i( int pane ) {
00466          if ( pane >= 0 && pane < activesubwindows.size() ) {
00467             activate( activesubwindows[pane]->getASCTXTname() );
00468             activesubwindows[pane]->update();
00469          }
00470          return true;
00471       }
00472 
00473       void activate( const ASCString& pane ) {
00474          BulkGraphicUpdates bgu( this );
00475          for ( int i = 0; i < activesubwindows.size(); ++i )
00476             if ( activesubwindows[i]->getASCTXTname() != pane )
00477                hide( activesubwindows[i]->getASCTXTname() );
00478 
00479          for ( int i = 0; i < activesubwindows.size(); ++i )
00480             if ( activesubwindows[i]->getASCTXTname() == pane )
00481                show( activesubwindows[i]->getASCTXTname() );
00482 
00483          for ( int i = 0; i< subWinButtons.size(); ++i )
00484             subWinButtons[i]->SetPressed( activesubwindows[i]->getASCTXTname() == pane );
00485       };
00486 
00487 
00488       void registerGuiFunctions( GuiIconHandler& handler ) {
00489          handler.registerUserFunction( new CargoGuiFunctions::Movement( *this ) );
00490          handler.registerUserFunction( new CargoGuiFunctions::RefuelUnitCommand( *this ) );
00491          handler.registerUserFunction( new CargoGuiFunctions::RefuelUnitDialogCommand( *this ) );
00492          handler.registerUserFunction( new CargoGuiFunctions::RepairUnit( *this ) );
00493          handler.registerUserFunction( new CargoGuiFunctions::UnitProduction( *this ));
00494          handler.registerUserFunction( new CargoGuiFunctions::UnitTraining( *this ));
00495          handler.registerUserFunction( new CargoGuiFunctions::MoveUnitUp( *this ));
00496          handler.registerUserFunction( new CargoGuiFunctions::MoveUnitIntoInnerContainer( *this ));
00497          handler.registerUserFunction( new CargoGuiFunctions::OpenContainer( *this ));
00498          handler.registerUserFunction( new CargoGuiFunctions::RecycleUnitCommandButton( *this ));
00499          handler.registerUserFunction( new CargoGuiFunctions::UnitInfo( *this ));
00500          handler.registerUserFunction( new CargoGuiFunctions::TransferUnitControl( *this ));
00501          handler.registerUserFunction( new CargoGuiFunctions::CloseDialog( *this ));
00502       }
00503 
00504       void checkStoringPosition( Vehicle* unit ) {
00505          if ( mainScreenWidget&& mainScreenWidget->getGuiHost() ) {
00506             mainScreenWidget->getGuiHost()->eval( container->getPosition(), unit );
00507          }
00508 
00509          if ( mainScreenWidget && mainScreenWidget->getUnitInfoPanel() )
00510             mainScreenWidget->getUnitInfoPanel()->showUnitData( unit, NULL, NULL, true );
00511       }
00512 
00513       void updateLoadMeter() {
00514          if ( container->baseType->maxLoadableWeight > 0 )
00515             setBargraphValue ( "LoadingMeter", float( container->cargoWeight()) / container->baseType->maxLoadableWeight );
00516       }
00517 
00518       void dragUnitToInnerContainer( Vehicle* draggedUnit, Vehicle* targetUnit ) {
00519          if ( !draggedUnit )
00520             return;
00521 
00522          if ( draggedUnit != targetUnit ) {
00523             if ( targetUnit && CargoMoveCommand::moveInAvail(draggedUnit, targetUnit) ) {
00524                auto_ptr<CargoMoveCommand> cargomove ( new CargoMoveCommand( draggedUnit ));
00525                cargomove->setMode( CargoMoveCommand::moveInwards );
00526                cargomove->setTargetCarrier( targetUnit );
00527                ActionResult res = cargomove->execute ( createContext( getContainer()->getMap() ));
00528                if ( res.successful() )
00529                   cargomove.release();
00530             } else {
00531                if ( container->getCarrier() && !targetUnit ) {
00532                   auto_ptr<CargoMoveCommand> cargomove ( new CargoMoveCommand( draggedUnit ));
00533                   cargomove->setMode( CargoMoveCommand::moveOutwards );
00534                   ActionResult res = cargomove->execute ( createContext( getContainer()->getMap() ));
00535                   if ( res.successful() )
00536                      cargomove.release();
00537                } else {
00538 
00539                }
00540             }
00541          }
00542          cargoChanged();
00543       }
00544 
00545       bool dragUnitToInnerContainerAvail( Vehicle* draggedUnit, Vehicle* targetUnit ) {
00546          return CargoMoveCommand::moveInAvail( draggedUnit, targetUnit );
00547       }
00548 
00549       void dragInProcess() {
00550          if ( mainScreenWidget && mainScreenWidget->getGuiHost() )
00551             mainScreenWidget->getGuiHost()->clearSmallIcons();
00552       }
00553 
00554       void dragAborted() {
00555          // to redraw everything
00556          cargoChanged();
00557       }
00558 
00559    public:
00560       int  getResourceValue ( int resourcetype, int y, int scope ) {
00561          int player = container->getMap()->actplayer;
00562          if ( container->getMap()->getCurrentPlayer().stat == Player::supervisor )
00563             player = container->getOwner();
00564 
00565          switch ( y ) {
00566             case 0: { // avail
00567                GetResource gr ( container->getMap() );
00568                return gr.getresource ( container->getPosition().x, container->getPosition().y, resourcetype, maxint, 1, player, scope );
00569             }
00570             case 1: { // tank
00571                GetResourceCapacity grc ( container->getMap() );
00572                return grc.getresource ( container->getPosition().x, container->getPosition().y, resourcetype, maxint, 1, player, scope );
00573             }
00574             case 2: { // plus
00575                GetResourcePlus grp ( container->getMap() );
00576                return grp.getresource ( container->getPosition().x, container->getPosition().y, resourcetype, player, scope );
00577             }
00578             case 3: { // usage
00579                GetResourceUsage gru( container->getMap() );
00580                return gru.getresource ( container->getPosition().x, container->getPosition().y, resourcetype, player, scope );
00581             }
00582          } /* endswitch */
00583          return -1;
00584       }
00585 
00586 
00587    public:
00588 
00589       CargoDialog (PG_Widget *parent, ContainerBase* cb );
00590 
00591       void addAvailableSubwin( SubWindow* w ) {
00592          activesubwindows.push_back( w );
00593       };
00594 
00595       void updateResourceDisplay() {
00596          setLabelText( "energyavail", container->getResource(maxint, 0, true ) );
00597          setLabelText( "materialavail", container->getResource(maxint, 1, true ) );
00598          setLabelText( "fuelavail", container->getResource(maxint, 2, true ) );
00599          setLabelText( "numericaldamage", container->damage );
00600       }
00601 
00602 
00603       Vehicle* getMarkedUnit() {
00604          if ( cargoWidget )
00605             return cargoWidget->getMarkedUnit();
00606          else
00607             return NULL;
00608       }
00609 
00610       void cargoChanged() {
00611          //unitHighLight.setNew( unitHighLight.getMark() );
00612          if ( cargoWidget ) {
00613             cargoWidget->redrawAll();
00614             if ( mainScreenWidget && mainScreenWidget->getUnitInfoPanel() )
00615                mainScreenWidget->getUnitInfoPanel()->showUnitData( cargoWidget->getMarkedUnit(), NULL, NULL, true );
00616 
00617             checkStoringPosition( cargoWidget->getMarkedUnit() );
00618          }
00619          sigCargoChanged();
00620          updateResourceDisplay();
00621          showAmmo();
00622          updateLoadMeter();
00623       }
00624 
00625       int RunModal() {
00626          if ( setupOK )
00627             return Panel::RunModal();
00628          return 0;
00629       }
00630 
00631       bool ProcessEvent ( const SDL_Event *   event,bool   bModal = false  ) {
00632          // the unit info panel must get the events first. If a unit is renamed and a character entered, this
00633          // key event shall go to the renaming - and not to the unit actions.
00634          if ( mainScreenWidget && mainScreenWidget->getUnitInfoPanel() )
00635             if ( mainScreenWidget->getUnitInfoPanel()->ProcessEvent( event, bModal ))
00636                return true;
00637 
00638          if ( mainScreenWidget && mainScreenWidget->getGuiHost() )
00639             if ( mainScreenWidget->getGuiHost()->ProcessEvent( event, bModal ))
00640                return true;
00641 
00642          if ( Panel::ProcessEvent( event, bModal ))
00643             return true;
00644 
00645          return false;
00646       }
00647 
00648       void showAmmo() {
00649          setLabelText( "cmmun", container->getAmmo( cwcruisemissile, maxint, true ));
00650          setLabelText( "minemun", container->getAmmo( cwminen, maxint, true ));
00651          setLabelText( "bombmun", container->getAmmo( cwbombn, maxint, true ));
00652          setLabelText( "lmmun", container->getAmmo( cwlargemissilen, maxint, true ));
00653          setLabelText( "smmun", container->getAmmo( cwsmallmissilen, maxint, true ));
00654          setLabelText( "mgmun", container->getAmmo( cwmachinegunn, maxint, true ));
00655          setLabelText( "canmun", container->getAmmo( cwcannonn, maxint, true ));
00656          setLabelText( "torpmun", container->getAmmo( cwtorpedon, maxint, true ));
00657       }
00658 
00659       void userHandler( const ASCString& label, PropertyReadingContainer& pc, PG_Widget* parent, WidgetParameters widgetParams );
00660 
00661       ContainerBase* getContainer() {
00662          return container;
00663       };
00664 
00665       GameMap* getMap() {
00666          if ( container ) return container->getMap();
00667          else return NULL;
00668       };
00669 
00670       SigC::Signal0<void>  sigCargoChanged;
00671 
00672       void setUnitInfoWidgets( const ContainerBase* container, const ASCString& prefix ) {
00673          if ( container ) {
00674             ASCString s;
00675             s.format( "%d / %d", container->cargoWeight(), container->baseType->maxLoadableWeight );
00676             setLabelText( prefix + "CargoUsage", s );
00677    
00678             int slots = 0;
00679             for ( ContainerBase::Cargo::const_iterator i = container->getCargo().begin(); i != container->getCargo().end(); ++i )
00680                if( *i )
00681                   ++slots;
00682                
00683             if ( container->baseType->maxLoadableUnits )
00684                setBargraphValue ( prefix + "LoadingMeter3", float( slots ) / float(container->baseType->maxLoadableUnits) );
00685             else
00686                setBargraphValue ( prefix + "LoadingMeter3", 0 );
00687    
00688             s.format( "%d / %d", slots, container->baseType->maxLoadableUnits );
00689             setLabelText( prefix + "SlotSummary", s );
00690             
00691             setLabelText( prefix + "UsedCargoSlots", slots );
00692             setLabelText( prefix + "CargoSlotCount", container->baseType->maxLoadableUnits );
00693             if ( container->baseType->maxLoadableUnits )
00694                setLabelText( prefix + "MaxLoadableWeight", container->baseType->maxLoadableWeight  );
00695             else
00696                setLabelText( prefix + "MaxLoadableWeight", "-"  );
00697             
00698             setLabelText( prefix + "UserName", container->name );
00699             setLabelText( prefix + "UnitTypeName", container->baseType->name );
00700             setLabelText( prefix + "UnitTypeDescription", container->baseType->description );
00701             
00702          } else {
00703             setLabelText( prefix + "CargoUsage", "" );
00704             setBargraphValue ( prefix + "LoadingMeter3", 0 );
00705             setLabelText( prefix + "UsedCargoSlots", "" );
00706             setLabelText( prefix + "CargoSlotCount", "" );
00707             setLabelText( prefix + "MaxLoadableWeight", ""  );
00708             
00709             setLabelText( prefix + "UserName", "" );
00710             setLabelText( prefix + "UnitTypeName", "" );
00711             setLabelText( prefix + "UnitTypeDescription", "" );
00712             
00713          }
00714       }
00715       
00716       void updateVariables( ) {
00717          PG_Widget* widget = this;
00718          // from solarpower
00719          {
00720             setLabelText( "MaxSolarPower", container->maxplus.energy );
00721 
00722             static const char* weathernames[] = {"terrain_weather_dry.png",
00723                                                  "terrain_weather_lightrain.png",
00724                                                  "terrain_weather_heavyrain.png",
00725                                                  "terrain_weather_lightsnow.png",
00726                                                  "terrain_weather_heavysnow.png",
00727                                                  "terrain_weather_ice.png"
00728                                                 };
00729 
00730 
00731             SolarPowerplant solarPowerPlant ( container );
00732             Resources plus = solarPowerPlant.getPlus();
00733             setLabelText( "CurrentSolarPower", plus.energy );
00734             setImage( "Weather", weathernames[ container->getMap()->getField( container->getPosition() )->getWeather() ], widget );
00735          }
00736 
00737          // from windpower
00738          {
00739             WindPowerplant windPowerPlant ( container );
00740             Resources plus = windPowerPlant.getPlus();
00741             setLabelText( "CurrentWindPower", plus.energy, widget );
00742 
00743 #ifdef WEATHERGENERATOR
00744             if ( container->getMap()->weatherSystem )
00745                setLabelText( "WindSpeed", container->getMap()->weatherSystem->getCurrentWindSpeed(), widget );
00746 #else
00747             setLabelText( "WindSpeed", container->getMap()->weather.windSpeed, widget );
00748 #endif
00749          }
00750 
00751          // from cargo
00752          {
00753             
00754             class MoveMalusType
00755             {
00756                public:
00757                   enum {  deflt,
00758                           light_tracked_vehicle,
00759                           medium_tracked_vehicle,
00760                           heavy_tracked_vehicle,
00761                           light_wheeled_vehicle,
00762                           medium_wheeled_vehicle,
00763                           heavy_wheeled_vehicle,
00764                           trooper,
00765                           rail_vehicle,
00766                           medium_aircraft,
00767                           medium_ship,
00768                           structure,
00769                           light_aircraft,
00770                           heavy_aircraft,
00771                           light_ship,
00772                           heavy_ship,
00773                           helicopter,
00774                           hoovercraft
00775                     };
00776             };
00777 
00778             setUnitInfoWidgets( container, "" );
00779 
00780             
00781             setUnitInfoWidgets( getMarkedUnit(), "Selected" );
00782             
00783             PG_Widget* typeImage = FindChild( "TypeImage", true );
00784             PG_ToolTipHelp* typeImageTooltip= NULL; 
00785             if ( typeImage ) 
00786                typeImageTooltip = PG_ToolTipHelp::GetToolTip( typeImage );
00787             
00788             if ( getMarkedUnit() ) {
00789                setLabelText( "CurrentCargo", getMarkedUnit()->weight(), widget );
00790                setImage( "TypeImage", moveMaliTypeIcons[getMarkedUnit()->typ->movemalustyp], widget );
00791                show( "TypeImage" );
00792                if ( typeImageTooltip )
00793                   typeImageTooltip->SetText( cmovemalitypes[getMarkedUnit()->typ->movemalustyp ] );
00794                
00795                if ( getMarkedUnit()->baseType->infoImageSmallFilename.length() > 0 ) {
00796                   setImage( "Selected3DImageSmall", getMarkedUnit()->baseType->infoImageSmallFilename, widget );
00797                   show( "Selected3DImageSmall" );
00798                } else
00799                   hide( "Selected3DImageSmall" );
00800                   
00801             } else {
00802                setLabelText( "CurrentCargo", "-" , widget );
00803                hide( "TypeImage" );
00804                hide( "Selected3DImageSmall" );
00805             }
00806 
00807             PG_Widget* w = FindChild( "SelectedImage", true );
00808             if ( w )
00809                w->Update();
00810             
00811             if ( container->baseType->maxLoadableWeight > 0 )
00812                setBargraphValue ( "LoadingMeter2", float( container->cargoWeight()) / container->baseType->maxLoadableWeight, widget );
00813 
00814             setLabelText("CargoWeight", container->cargoWeight() );
00815             
00816             if ( container->baseType->maxLoadableWeight >= 1000000 ) {
00817                setLabelText ( "FreeWeight", "unlimited", widget );
00818                setLabelText ( "MaxWeight",  "unlimited", widget );
00819             } else {
00820                setLabelText ( "FreeWeight", container->baseType->maxLoadableWeight - container->cargoWeight(), widget );
00821                setLabelText ( "MaxWeight",  container->baseType->maxLoadableWeight, widget );
00822             }
00823 
00824             setLabelText ( "FreeSlots", container->baseType->maxLoadableUnits - container->vehiclesLoaded(), widget );
00825             setLabelText ( "MaxSlots",  container->baseType->maxLoadableUnits , widget );
00826             setLabelText ( "MaxUnitSize",  container->baseType->maxLoadableUnitSize, widget );
00827          }
00828 
00829          // from buildingcontrol
00830          {
00831             Building* bld = dynamic_cast<Building*>( container );
00832             if ( bld ) {
00833                if ( RepairBuildingCommand::avail( bld )) {
00834                   RepairBuildingCommand rbc( bld );
00835                   RepairBuildingCommand::RepairData repairData = rbc.getCost();
00836                   setLabelText( "RepairCostLabel", "Cost for repairing " + ASCString::toString( repairData.damageDelta ) + "%", widget );
00837 
00838                   setLabelText( "EnergyCost", repairData.cost.energy, widget );
00839                   setLabelText( "MaterialCost", repairData.cost.material, widget );
00840                   setLabelText( "FuelCost", repairData.cost.fuel, widget );
00841 
00842                } else {
00843                   setLabelText( "RepairCostLabel", "No repair possible", widget );
00844 
00845                   setLabelText( "EnergyCost", "-", widget );
00846                   setLabelText( "MaterialCost", "-", widget );
00847                   setLabelText( "FuelCost", "-", widget );
00848                }
00849             }
00850             setLabelText( "Jamming", container->baseType->jamming , widget );
00851             setLabelText( "View", container->baseType->view, widget );
00852             setLabelText( "Armor", container->getArmor(), widget );
00853          }
00854 
00855       }
00856 
00857 
00858       ~CargoDialog() {
00859          if ( setupOK )
00860             NewGuiHost::popIconHandler();
00861 
00862       }
00863 
00864 };
00865 
00866 
00867 
00868 
00869 
00870 void cargoDialog( ContainerBase* cb )
00871 {
00872    CargoDialog cd ( NULL, cb );
00873    cd.Show();
00874    cd.RunModal();
00875 }
00876 
00877 
00878 
00879 
00880 /*
00881 const Vehicletype* selectVehicletype( ContainerBase* plant, const vector<Vehicletype*>& items )
00882 {
00883    VehicleTypeSelectionWindow fsw( NULL, PG_Rect( 10, 10, 400, 500 ), plant, items );
00884    fsw.Show();
00885    fsw.RunModal();
00886    const Vehicletype* v = fsw.getVehicletype();
00887    return v;
00888 }
00889 
00890 */
00891 
00892 
00893 void SubWindow::registerSubwindow( CargoDialog* cd )
00894 {
00895    cargoDialog = cd;
00896    cd->addAvailableSubwin( this );
00897 }
00898 
00899 void SubWindow::registerChilds( CargoDialog* cd )
00900 {
00901    widget = cd->FindChild( getASCTXTname(), true);
00902    if ( !widget )
00903       warningMessage( "Could not find widget with name " + getASCTXTname() );
00904 }
00905 
00906 
00907 ContainerBase* SubWindow::container()
00908 {
00909    return cargoDialog->getContainer();
00910 }
00911 
00912 /*
00913 const int subWindowNum = 11;
00914 static const char* subWindowName[subWindowNum] =
00915 { "ammotransfer", "ammoproduction", "info", "cargoinfo", "conventionalpower", "mining", "netcontrol", "research", "resourceinfo", "solarpower", "windpower"
00916 };
00917 */
00918 
00919 
00920 
00921 class SolarPowerWindow : public SubWindow
00922 {
00923 
00924    public:
00925       bool available( CargoDialog* cd ) {
00926          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
00927             return false;
00928 
00929          return cd->getContainer()->baseType->hasFunction( ContainerBaseType::SolarPowerPlant  );
00930       };
00931 
00932       ASCString getASCTXTname() {
00933          return "solarpower";
00934       };
00935 
00936       ASCString getFullName() {
00937          return "Solar Power Generation";
00938       };
00939 
00940       void update() {
00941          cargoDialog->updateVariables();
00942       }
00943 };
00944 
00945 class WindPowerWindow : public SubWindow
00946 {
00947    public:
00948       bool available( CargoDialog* cd ) {
00949          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
00950             return false;
00951 
00952          return cd->getContainer()->baseType->hasFunction( ContainerBaseType::WindPowerPlant  );
00953       };
00954 
00955       ASCString getASCTXTname() {
00956          return "windpower";
00957       };
00958 
00959       ASCString getFullName() {
00960          return "Wind Power Generation";
00961       };
00962 
00963 
00964       void update() {
00965          cargoDialog->updateVariables();
00966       }
00967 };
00968 
00969 class NetControlWindow : public SubWindow
00970 {
00971 
00972    private:
00973 
00974       bool click( PG_Button* b, int x, int y ) {
00975          return true;
00976       }
00977 
00978       PG_Button* findButton( int x, int y ) {
00979          char c = 'a' + x;
00980          ASCString buttonName = "Button" + ASCString::toString(y) + c;
00981          return dynamic_cast<PG_Button*>( widget->FindChild( buttonName, true ) );
00982       }
00983 
00984    public:
00985       bool available( CargoDialog* cd ) {
00986          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
00987             return false;
00988 
00989          return dynamic_cast<Building*>(cd->getContainer()) != NULL;
00990       };
00991 
00992       ASCString getASCTXTname() {
00993          return "netcontrol";
00994       };
00995 
00996       ASCString getFullName() {
00997          return "Resource Network Control";
00998       };
00999 
01000 
01001       void registerChilds( CargoDialog* cd ) {
01002          SubWindow::registerChilds( cd );
01003 
01004          if ( widget ) {
01005             for ( int x = 0; x < 3; ++x ) {
01006                for ( int y = 0; y < 4; ++y ) {
01007                   PG_Button* b = findButton( x, y );
01008                   if ( b ) {
01009                      b->sigClick.connect( SigC::bind( SigC::bind( SigC::slot( *this, &NetControlWindow::click ), x), y));
01010                      if ( y >= 2)
01011                         b->SetToggle( true );
01012                   }
01013 
01014                }
01015             }
01016 
01017          }
01018       }
01019 
01020       void update() {
01021          cargoDialog->updateVariables();
01022       }
01023 };
01024 
01025 
01026 class CargoInfoWindow : public SubWindow
01027 {
01028    public:
01029       bool available( CargoDialog* cd ) {
01030          return true;
01031       };
01032 
01033       ASCString getASCTXTname() {
01034          return "cargoinfo";
01035       };
01036 
01037       ASCString getFullName() {
01038          return "Cargo Info";
01039       };
01040 
01041       void registerSubwindow( CargoDialog* cd ) {
01042          SubWindow::registerSubwindow( cd );
01043          cargoDialog->sigCargoChanged.connect( SigC::slot( *this, &CargoInfoWindow::update ));
01044       };
01045 
01046 
01047       void registerChilds( CargoDialog* cd ) {
01048          SubWindow::registerChilds( cd );
01049 
01050       }
01051 
01052       void update() {
01053          cargoDialog->updateVariables();
01054       }
01055 };
01056 
01057 
01058 class BuildingControlWindow : public SubWindow
01059 {
01060    public:
01061       SigC::Signal0<void> damageChanged;
01062 
01063 
01064       void registerChilds( CargoDialog* cd ) {
01065          SubWindow::registerChilds( cd );
01066 
01067          if ( widget ) {
01068             PG_Button* b = dynamic_cast<PG_Button*>( widget->FindChild( "RepairButton", true ) );
01069             if ( b )
01070                b->sigClick.connect( SigC::slot( *this, &BuildingControlWindow::repair ));
01071          }
01072       }
01073 
01074       bool repair() {
01075          Building* bld = dynamic_cast<Building*>(container() );
01076          if ( !RepairBuildingCommand::avail( bld ))
01077             return false;
01078 
01079          auto_ptr<RepairBuildingCommand> rbc ( new RepairBuildingCommand( bld ));
01080          ActionResult res = rbc->execute( createContext( container()->getMap() ));
01081          if  ( res.successful() )
01082             rbc.release();
01083          else
01084             displayActionError( res );
01085 
01086          cargoDialog->updateResourceDisplay();
01087 
01088          damageChanged();
01089          update();
01090 
01091          if  ( widget )
01092             widget->Update();
01093 
01094          return true;
01095       }
01096 
01097 
01098       bool available( CargoDialog* cd ) {
01099          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
01100             return false;
01101 
01102          Building* bld = dynamic_cast<Building*>(cd->getContainer());
01103          if ( !bld )
01104             return false;
01105 
01106          return true;
01107 
01108          // return RepairBuildingCommand::avail(  ));
01109       };
01110 
01111       ASCString getASCTXTname() {
01112          return "damagecontrol";
01113       };
01114 
01115       ASCString getFullName() {
01116          return "Building Control";
01117       };
01118 
01119 
01120       void update() {
01121          cargoDialog->updateVariables();
01122 
01123          damageChanged(); // it didn't really change, but we are triggering a redraw
01124       }
01125 };
01126 
01127 
01128 class ResourceInfoWindow : public SubWindow
01129 {
01130 
01131 
01132    public:
01133       bool available( CargoDialog* cd ) {
01134          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ) && cd->getMap()->getCurrentPlayer().stat != Player::supervisor )
01135             return false;
01136 
01137          return dynamic_cast<Building*>( cd->getContainer() ) != NULL;
01138       };
01139 
01140       ASCString getASCTXTname() {
01141          return "resourceinfo";
01142       };
01143 
01144       ASCString getFullName() {
01145          return "Resource Network Information";
01146       };
01147 
01148 
01149       void update() {
01150 
01151          ContainerBase* activeContainer= container();
01152 
01153          int value[3][3][4];
01154          int mx = 0;
01155 
01156          for ( int c = 0; c < 3; c++ )
01157             for ( int x = 0; x < 3; x++ )
01158                for ( int y = 0; y < 4; y++ ) {
01159                   value[c][x][y] = cargoDialog->getResourceValue ( x, y, c );
01160                   if ( y != 1 )
01161                      if ( value[c][x][y] > mx )
01162                         mx = value[c][x][y];
01163                }
01164 
01165 
01166 
01167          for ( int c = 0; c < 3; c++ )
01168             for ( int x = 0; x < 3; x++ )
01169                for ( int y = 0; y < 4; y++ ) {
01170                   char xx = 'A' + (c * 3 + x);
01171                   char yy = '1' + y;
01172                   ASCString label = "Res";
01173                   label += xx;
01174                   label += yy;
01175                   if ( (y != 1 || value[c][x][y] < mx*10 || value[c][x][y] < 1000000000 ) && ( !activeContainer->getMap()->isResourceGlobal(x) || y!=0 ||c ==2))   // don't show extremely high numbers
01176                      cargoDialog->setLabelText( label, value[c][x][y] );
01177                   else
01178                      cargoDialog->setLabelText( label, "-" );
01179                }
01180 
01181       }
01182 
01183 };
01184 
01185 
01186 class GraphWidget : public PG_Widget
01187 {
01188       map<int,int> verticalLines;
01189       vector<int> curves;
01190       typedef vector< pair<int,int> > Bars;
01191       Bars bars;
01192    protected:
01193       int xrange;
01194       int yrange;
01195       virtual int getPoint( int curve, int x ) {
01196          return 0;
01197       };
01198       virtual int getBarHeight( int bar ) {
01199          return 0;
01200       };
01201       virtual void click( int x, int button ) {};
01202 
01203       bool   eventMouseMotion (const SDL_MouseMotionEvent *motion) {
01204          PG_Point p = ScreenToClient ( motion->x, motion->y );
01205          if ( motion->type == SDL_MOUSEMOTION && (motion->state == SDL_BUTTON(1)))
01206             click ( p.x, 1 );
01207 
01208          if ( motion->type == SDL_MOUSEMOTION && (motion->state == SDL_BUTTON(3)))
01209             click( p.x, 3 );
01210 
01211          return true;
01212       }
01213 
01214       bool   eventMouseButtonDown (const SDL_MouseButtonEvent *button) {
01215          PG_Point p = ScreenToClient ( button->x, button->y );
01216          if ( button->type == SDL_MOUSEBUTTONDOWN && (button->button == SDL_BUTTON_LEFT))
01217             click ( p.x, 1 );
01218 
01219          if ( button->type == SDL_MOUSEBUTTONDOWN && (button->button == SDL_BUTTON_RIGHT))
01220             click ( p.x, 3 );
01221 
01222          return true;
01223       }
01224 
01225       int mapColor( int col ) {
01226          PG_Color color = col;
01227          return color.MapRGBA( PG_Application::GetScreen()->format, 255-GetTransparency());
01228       }
01229 
01230    public:
01231       GraphWidget( PG_Widget *parent, const PG_Rect& rect ) : PG_Widget( parent, rect ), xrange(1), yrange(1) {};
01232       void setRange( int x, int y ) {
01233          xrange = max( x, 1);
01234          yrange = max( y, 1);
01235       }
01236 
01237       int addCurve( int color ) {
01238          curves.push_back( color );
01239          return curves.size();
01240       }
01241 
01242       int addBar( int pos, int color ) {
01243          bars.push_back ( make_pair( pos, color ));
01244          return bars.size();
01245       }
01246 
01247 
01248       void addVerticalLine ( int x, int color ) {
01249          verticalLines[x] = color;
01250       }
01251 
01252       void clearVerticalLines() {
01253          verticalLines.clear();
01254       }
01255 
01256       void eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst) {
01257          Surface s = Surface::Wrap( PG_Application::GetScreen() );
01258 
01259          for ( int c = 0; c < curves.size(); ++c ) {
01260             int realcol = mapColor( curves[c] );
01261 
01262             for ( int x = 0; x < Width(); ++x ) {
01263                int y = getPoint( c, x * xrange / Width() ) * Height() / yrange;
01264                if ( y < 0 )
01265                   y = 0;
01266                if ( y >= Height() )
01267                   y = Height() -1 ;
01268                PG_Point pos = ClientToScreen( x, Height() - y );
01269                s.SetPixel( pos.x, pos.y, realcol );
01270             }
01271          }
01272 
01273          for ( map<int,int>::iterator v = verticalLines.begin(); v != verticalLines.end(); ++v ) {
01274             int realcol = mapColor( v->second );
01275 
01276             int x = v->first * Width() / xrange;
01277             for ( int y = 0; y < Height(); ++y ) {
01278                PG_Point pos = ClientToScreen( x, y );
01279                s.SetPixel( pos.x, pos.y, realcol );
01280             }
01281          }
01282          int barNum = 0;
01283          for ( Bars::iterator b = bars.begin(); b != bars.end(); ++b ) {
01284             int x = b->first * Width() / (xrange+1);
01285             int x2 = (b->first + 1) * Width() / xrange - 1;
01286             if ( x2 <= x )
01287                x2 = x + 1;
01288 
01289             int y = getBarHeight( barNum ) * Height() / yrange;
01290             if ( y < 0 )
01291                y = 0;
01292             if ( y >= Height() )
01293                y = Height() -1 ;
01294 
01295             PG_Point pos = ClientToScreen( x, Height() - y );
01296             paintFilledRectangle<4>( s, SPoint( pos.x, pos.y), x2-x, y, ColorMerger_ColoredOverwrite<4>( mapColor( b->second ) ) );
01297 
01298             ++barNum;
01299          }
01300       };
01301 };
01302 
01303 class ResearchGraph : public GraphWidget
01304 {
01305       ContainerBase* cont;
01306    protected:
01307       int getPoint( int curve, int x ) {
01308          Resources cost = returnResourcenUseForResearch( cont, x );
01309          return cost.energy;
01310       }
01311 
01312 
01313       void addSecondaryLab( ContainerBase* lab ) {
01314          if ( lab->baseType->nominalresearchpoints && lab->baseType->hasFunction( ContainerBaseType::Research  ) ) {
01315             int rel = lab->researchpoints * cont->baseType->nominalresearchpoints / lab->baseType->nominalresearchpoints;
01316             addVerticalLine( rel, 0xd9d9d9 );
01317          }
01318       }
01319 
01320       void recalc() {
01321          clearVerticalLines();
01322 
01323          Player& player = cont->getMap()->player[ cont->getOwner() ];
01324          for ( Player::BuildingList::iterator i = player.buildingList.begin(); i != player.buildingList.end(); ++i )
01325             addSecondaryLab( *i );
01326 
01327          for ( Player::VehicleList::iterator i = player.vehicleList.begin(); i != player.vehicleList.end(); ++i )
01328             addSecondaryLab( *i );
01329 
01330          addVerticalLine( cont->researchpoints, 0xd5d200 );
01331       }
01332 
01333       bool setResearch ( ContainerBase* lab, int x ) {
01334          if ( cont->baseType->nominalresearchpoints ) {
01335             int res;
01336 
01337             if ( returnResourcenUseForResearch ( lab, lab->maxresearchpoints ) == Resources(0,0,0))
01338                res = lab->maxresearchpoints;
01339             else
01340                res = x * xrange / Width() * lab->baseType->nominalresearchpoints / cont->baseType->nominalresearchpoints;
01341 
01342             if ( res > lab->maxresearchpoints )
01343                res = lab->maxresearchpoints;
01344             int old = lab->researchpoints;
01345             lab->researchpoints = res;
01346             return res != old;
01347          } else
01348             return false;
01349       }
01350 
01351 
01352       void click( int x, int button ) {
01353          setResearch( x, button == 3 );
01354       }
01355 
01356       void setResearch( int x, bool global = false ) {
01357          if ( global ) {
01358             Player& player = cont->getMap()->player[ cont->getOwner() ];
01359             for ( Player::BuildingList::iterator i = player.buildingList.begin(); i != player.buildingList.end(); ++i )
01360                setResearch( *i, x );
01361 
01362             for ( Player::VehicleList::iterator i = player.vehicleList.begin(); i != player.vehicleList.end(); ++i )
01363                setResearch( *i, x );
01364          }
01365 
01366          if ( setResearch( cont, x ) || global ) {
01367             sigChange();
01368             recalc();
01369             Update();
01370          }
01371       }
01372 
01373    public:
01374       ResearchGraph( PG_Widget *parent, const PG_Rect& rect, ContainerBase* container ) : GraphWidget( parent, rect ), cont( container ) {
01375          setRange( cont->maxresearchpoints+1, returnResourcenUseForResearch( cont, cont->maxresearchpoints ).energy );
01376          addCurve( 0x00ff00 );
01377          recalc();
01378       }
01379 
01380       SigC::Signal0<void> sigChange;
01381 
01382 };
01383 
01384 
01385 class ResearchWindow : public SubWindow
01386 {
01387    public:
01388       bool available( CargoDialog* cd ) {
01389          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
01390             return false;
01391 
01392          return cd->getContainer()->baseType->hasFunction( ContainerBaseType::Research  );
01393       };
01394 
01395       ASCString getASCTXTname() {
01396          return "research";
01397       };
01398 
01399       ASCString getFullName() {
01400          return "Research Lab";
01401       };
01402 
01403 
01404       void update() {
01405          ContainerBase* activeContainer= container();
01406          
01407          // from researchwindow
01408          Player& player = activeContainer->getMap()->player[ activeContainer->getOwner() ];
01409 
01410          cargoDialog->setLabelText( "ResPerTurnLocal", activeContainer->researchpoints *  player.research.getMultiplier(), widget );
01411          cargoDialog->setLabelText( "ResPerTurnGlobal", player.research.getResearchPerTurn(), widget );
01412 
01413          Resources cost = returnResourcenUseForResearch( activeContainer );
01414          for ( int r = 0; r < 3; ++r)
01415             cargoDialog->setLabelText( "CostLocal" + ASCString::toString(r), cost.resource(r), widget );
01416 
01417          Resources globalCost;
01418          for ( Player::BuildingList::iterator i = player.buildingList.begin(); i != player.buildingList.end(); ++i )
01419             globalCost += returnResourcenUseForResearch( *i );
01420 
01421          for ( Player::VehicleList::iterator i = player.vehicleList.begin(); i != player.vehicleList.end(); ++i )
01422             globalCost += returnResourcenUseForResearch( *i );
01423 
01424          for ( int r = 0; r < 3; ++r)
01425             cargoDialog->setLabelText( "CostGlobal" + ASCString::toString(r), globalCost.resource(r), widget );
01426 
01427          int availIn = player.research.currentTechAvailableIn();
01428          if ( availIn >= 0 )
01429             cargoDialog->setLabelText( "AvailGlobal", availIn, widget );
01430          else
01431             cargoDialog->setLabelText( "AvailGlobal", "-", widget );
01432 
01433          if ( player.research.activetechnology )
01434             cargoDialog->setLabelText( "CurrentTech", player.research.activetechnology->name, widget );
01435          else
01436             cargoDialog->setLabelText( "CurrentTech", "-", widget );
01437       }
01438 };
01439 
01440 
01441 
01442 class MatterAndMiningBaseWindow : public SubWindow
01443 {
01444       PG_Slider* slider;
01445       bool first;
01446 
01447    protected:
01448       virtual bool invertSlider() {
01449          return false;
01450       };
01451    private:
01452 
01453       bool scrollPos( long pos ) {
01454          if ( invertSlider() )
01455             pos = 100 - pos;
01456 
01457          setnewpower( pos );
01458          update();
01459          return true;
01460       };
01461 
01462 
01463       bool scrollTrack( long pos ) {
01464 
01465          if ( invertSlider() )
01466             pos = 100 - pos;
01467 
01468          showResourceTable( getOutput( pos ));
01469 
01470          return true;
01471       };
01472 
01473       void setnewpower ( ContainerBase* c, int power ) {
01474          if ( hasFunction( c ) ) {
01475             auto_ptr<SetResourceProcessingRateCommand> srprc ( new SetResourceProcessingRateCommand( c, power ));
01476 
01477             ActionResult res = srprc->execute( createContext( c->getMap() ));
01478             if ( res.successful() )
01479                srprc.release();
01480             else
01481                displayActionError( res );
01482          }
01483       }
01484 
01485       void setnewpower ( int pwr ) {
01486          if ( pwr < 0 )
01487             pwr = 0;
01488 
01489          if ( pwr > 100 )
01490             pwr = 100;
01491 
01492          bool allbuildings = false;
01493 
01494          Player& player = container()->getMap()->player[ container()->getOwner() ];
01495 
01496          if ( allbuildings ) {
01497             for ( Player::BuildingList::iterator bi = player.buildingList.begin(); bi != player.buildingList.end(); bi++ )
01498                setnewpower( *bi, pwr );
01499             for ( Player::VehicleList::iterator bi = player.vehicleList.begin(); bi != player.vehicleList.end(); bi++ )
01500                setnewpower( *bi, pwr );
01501          } else {
01502             setnewpower( container(), pwr );
01503          }
01504       }
01505 
01506       virtual bool hasFunction( const ContainerBase* container ) = 0;
01507 
01508       bool available( CargoDialog* cd ) {
01509          if ( !cd->getMap()->getCurrentPlayer().diplomacy.isAllied( cd->getContainer() ))
01510             return false;
01511 
01512          return hasFunction( cd->getContainer() );
01513       };
01514 
01515       virtual Resources getOutput() = 0;
01516       virtual Resources getOutput( int rate ) = 0;
01517 
01518    private:
01519       void showResourceTable( const Resources& res ) {
01520          for ( int r = 0; r < 3; ++r ) {
01521             ASCString s = Resources::name(r);
01522             int amount = res.resource(r);
01523             if ( container()->maxplus.resource(r) < 0 ) {
01524                s += "In";
01525                amount  = -amount;
01526             } else {
01527                s += "Out";
01528             }
01529             if ( container()->maxplus.resource(r) != 0 )
01530                cargoDialog->setLabelText( s, amount, widget );
01531          }
01532       }
01533 
01534    public:
01535       MatterAndMiningBaseWindow () : slider(NULL), first(true) {};
01536 
01537 
01538       void update() {
01539          cargoDialog->updateVariables();
01540 
01541          if ( widget )
01542             slider = dynamic_cast<PG_Slider*>( widget->FindChild( "PowerSlider", true ));
01543 
01544          if ( first && slider ) {
01545             first = false;
01546             slider->SetRange( 0, 100 );
01547             slider->sigScrollPos.connect( SigC::slot( *this, &MatterAndMiningBaseWindow::scrollPos ));
01548             slider->sigScrollTrack.connect( SigC::slot( *this, &MatterAndMiningBaseWindow::scrollTrack ));
01549          }
01550 
01551          for ( int r = 0; r < 3; ++r )
01552             if ( container()->maxplus.resource(r) ) {
01553                slider->SetPosition( 100 * container()->plus.resource(r) / container()->maxplus.resource(r) );
01554                break;
01555             }
01556 
01557          showResourceTable( getOutput() );
01558       }
01559 };
01560 
01561 class MatterConversionWindow : public MatterAndMiningBaseWindow
01562 {
01563    protected:
01564       bool hasFunction( const ContainerBase* container ) {
01565          return container->baseType->hasFunction( ContainerBaseType::MatterConverter );
01566       };
01567 
01568       Resources getOutput() {
01569          return container()->plus;
01570       }
01571 
01572       Resources getOutput( int rate ) {
01573          Resources r;
01574          for ( int i = 0; i < Resources::count; ++i )
01575             r.resource(i) = rate * container()->maxplus.resource(i) / 100;
01576          return r;
01577       }
01578 
01579 
01580    public:
01581 
01582       ASCString getASCTXTname() {
01583          return "conventionalpower";
01584       };
01585 
01586       ASCString getFullName() {
01587          return "Power Generation";
01588       };
01589 
01590 };
01591 
01592 
01593 
01594 class MiningGraph : public GraphWidget
01595 {
01596       ContainerBase* cont;
01597       GetMiningInfo::MiningInfo mininginfo;
01598    protected:
01599 
01600       int getBarHeight( int bar ) {
01601          int r = (bar % 4) - 1;
01602          switch ( bar % 4 ) {
01603             case 0:
01604             case 1:
01605                return 100;
01606             case 2:
01607             case 3:
01608                return 100 * mininginfo.avail[bar/4].resource(r) / mininginfo.max[bar/4].resource(r);
01609          };
01610          return 0;
01611       };
01612 
01613 
01614    public:
01615       MiningGraph( PG_Widget *parent, const PG_Rect& rect, ContainerBase* container ) : GraphWidget( parent, rect ), cont( container ) {
01616          setRange( (maxminingrange+1)*3+1, 110 );
01617 
01618          GetMiningInfo gmi ( container );
01619          mininginfo = gmi.getMiningInfo();
01620 
01621          int neutralColor = 0x666666;
01622 
01623          for ( int i = 0; i <= min( mininginfo.nextMiningDistance + 1, maxminingrange); ++i ) {
01624             addBar( i * 3, neutralColor );
01625             addBar( i * 3+1, neutralColor );
01626             addBar( i * 3, Resources::materialColor );
01627             addBar( i * 3+1, Resources::fuelColor );
01628          }
01629 
01630       }
01631 };
01632 
01633 
01634 class MiningWindow : public MatterAndMiningBaseWindow
01635 {
01636    protected:
01637       bool hasFunction( const ContainerBase* container ) {
01638          return container->baseType->hasFunction( ContainerBaseType::MiningStation );
01639       };
01640 
01641       bool invertSlider() {
01642          return false;
01643       };
01644 
01645       Resources getOutput() {
01646          Resources r;
01647          MiningStation miningStation ( container(), true );
01648 
01649          for ( int i = 0; i <3; ++i ) {
01650             Resources plus = miningStation.getPlus();
01651             if ( plus.resource(i) > 0 )
01652                r.resource(i) = plus.resource(i);
01653 
01654             Resources usage = miningStation.getUsage();
01655             if ( usage.resource(i) > 0 )
01656                r.resource(i) = -usage.resource(i);
01657          }
01658          return r;
01659       }
01660 
01661       Resources getOutput( int rate ) {
01662          ContainerBase* c = container();
01663          Resources temp = c->plus;
01664 
01665          for ( int r = 0; r < Resources::count; r++ )
01666             c->plus.resource(r) = c->maxplus.resource(r) * rate/100;
01667 
01668 
01669          Resources r;
01670          MiningStation miningStation ( container(), true );
01671 
01672          for ( int i = 0; i <3; ++i ) {
01673             Resources plus = miningStation.getPlus();
01674             if ( plus.resource(i) > 0 )
01675                r.resource(i) = plus.resource(i);
01676 
01677             Resources usage = miningStation.getUsage();
01678             if ( usage.resource(i) > 0 )
01679                r.resource(i) = -usage.resource(i);
01680          }
01681 
01682          c->plus = temp;
01683 
01684          return r;
01685       }
01686 
01687    public:
01688 
01689       ASCString getASCTXTname() {
01690          return "mining";
01691       };
01692 
01693       ASCString getFullName() {
01694          return "Mining Facility";
01695       };
01696 
01697 
01698       void update() {
01699          MatterAndMiningBaseWindow::update();
01700       }
01701 };
01702 
01703 
01704 
01705 class DamageBarWidget : public PG_ThemeWidget
01706 {
01707    private:
01708       ContainerBase* container;
01709    public:
01710       DamageBarWidget (PG_Widget *parent, const PG_Rect &rect, ContainerBase* container ) : PG_ThemeWidget( parent, rect, false ) {
01711          this->container = container;
01712       };
01713 
01714 
01715       void repaint() {
01716          Update();
01717       }
01718 
01719       void eventBlit (SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst) {
01720          DI_Color color( container->damage * 255 / 100, (100-container->damage) * 255/100, 0  );
01721 
01722          PG_Rect r = dst;
01723          r.w = (100 - container->damage ) * dst.w / 100;
01724 
01725          Resources cost;
01726          int w2 = (100 - container->damage + container->repairableDamage() ) * dst.w / 100;
01727 
01728          Uint32 c = color.MapRGBA( PG_Application::GetScreen()->format, 255-GetTransparency());
01729          if ( w > 0 ) {
01730             SDL_FillRect(PG_Application::GetScreen(), &r, c );
01731          }
01732 
01733          if ( w2 > 0 ) {
01734             int h = dst.h / 4;
01735             Surface s = Surface::Wrap( PG_Application::GetScreen() );
01736             ColorMerger_Set<4> cm ( c );
01737             drawLine<4> ( s, cm, SPoint(dst.x, dst.y + h), SPoint( dst.x + w2, dst.y + h));
01738             drawLine<4> ( s, cm, SPoint(dst.x, dst.y + h+1), SPoint( dst.x + w2, dst.y + h+1));
01739             drawLine<4> ( s, cm, SPoint(dst.x, dst.y + dst.h - h-1), SPoint( dst.x + w2, dst.y + dst.h - h-1));
01740             drawLine<4> ( s, cm, SPoint(dst.x, dst.y + dst.h - h), SPoint( dst.x + w2, dst.y + dst.h - h));
01741             drawLine<4> ( s, cm, SPoint( dst.x + w2, dst.y), SPoint( dst.x + w2, dst.y + dst.h));
01742             drawLine<4> ( s, cm, SPoint( dst.x-1 + w2, dst.y), SPoint( dst.x-1 + w2, dst.y + dst.h));
01743          }
01744 
01745          /*         Uint32 c = color.MapRGBA( PG_Application::GetScreen()->format, 255-GetTransparency());
01746                   for ( Colors::iterator i = colors.begin(); i != colors.end(); ++i)
01747                      if ( fraction < i->first ) {
01748                      PG_Color col = i->second;
01749                      c = col.MapRGBA( PG_Application::GetScreen()->format, 255-GetTransparency());
01750                      }
01751          */
01752 
01753 
01754       }
01755 
01756 };
01757 
01758 
01759 
01760 
01761 //*****************************************************************************************************
01762 //*****************************************************************************************************
01763 //
01764 //  Cargo Dialog
01765 //
01766 //*****************************************************************************************************
01767 //*****************************************************************************************************
01768 
01769 
01770 
01771 CargoDialog ::CargoDialog (PG_Widget *parent, ContainerBase* cb )
01772       : Panel( parent, PG_Rect::null, "cargodialog", false ), container(cb), setupOK(false), cargoWidget(NULL), researchWindow( NULL ), matterWindow(NULL)
01773 {
01774    shutdownImmediately = false;
01775 
01776    sigClose.connect( SigC::slot( *this, &CargoDialog::QuitModal ));
01777 
01778    registerGuiFunctions( guiIconHandler );
01779 
01780    cb->destroyed.connect( SigC::slot( *this, &CargoDialog::containerDestroyed ));
01781 
01782    ciw = new CargoInfoWindow;
01783    subwindows.push_back( ciw );
01784    subwindows.push_back( new SolarPowerWindow );
01785    subwindows.push_back( new WindPowerWindow );
01786    subwindows.push_back( new MiningWindow );
01787    subwindows.push_back( new ResourceInfoWindow );
01788    // subwindows.push_back( new NetControlWindow );
01789 
01790    buildingControlWindow = new BuildingControlWindow;
01791    subwindows.push_back( buildingControlWindow );
01792 
01793    researchWindow = new ResearchWindow;
01794    subwindows.push_back( researchWindow );
01795 
01796    matterWindow = new MatterConversionWindow;
01797    subwindows.push_back ( matterWindow );
01798 
01799    for ( Subwindows::iterator i = subwindows.begin(); i != subwindows.end(); ++i )
01800       if ( (*i)->available( this ))
01801          (*i)->registerSubwindow( this );
01802 
01803 
01804 
01805    // cb->resourceChanged.connect( SigC::slot( *this, &CargoDialog::updateResourceDisplay ));
01806    // cb->ammoChanged.connect( SigC::slot( *this, &CargoDialog::showAmmo ));
01807 
01808 
01809    try {
01810       if ( !setup() )
01811          return;
01812 
01813       // to not block the weapon info on 800*600 screens
01814 
01815       if ( my_xpos + Width() > PG_Application::GetScreenWidth() - 100 )
01816          MoveWidget( 0, 0, false);
01817 
01818 
01819    } catch ( ParsingError err ) {
01820       errorMessage( err.getMessage() );
01821       return;
01822    } catch ( ... ) {
01823       errorMessage( "unknown exception" );
01824       return;
01825    }
01826 
01827    registerSpecialDisplay( "unitpad_unitsymbol" );
01828    registerSpecialDisplay( "SelectedImage" );
01829 
01830 
01831    for ( Subwindows::iterator i = subwindows.begin(); i != subwindows.end(); ++i ) {
01832       if ( (*i)->available( this ))
01833          (*i)->registerChilds( this );
01834       hide( (*i)->getASCTXTname() );
01835    }
01836 
01837 
01838 
01839    if ( !cb->baseType->infoImageFilename.empty() && exist( cb->baseType->infoImageFilename )) {
01840       PG_Image* img = dynamic_cast<PG_Image*>(FindChild( "ContainerImage", true ));
01841       if ( img ) {
01842          tnfilestream stream ( cb->baseType->infoImageFilename, tnstream::reading );
01843          infoImage.readImageFile( stream );
01844          img->SetDrawMode( PG_Draw::STRETCH );
01845          img->SetImage( infoImage.getBaseSurface(), false );
01846          img->SizeWidget( img->GetParent()->w, img->GetParent()->h );
01847       }
01848    } else {
01849       PG_Image* img = dynamic_cast<PG_Image*>(FindChild( "ContainerImage", true ));
01850       Vehicle* v = dynamic_cast<Vehicle*>(cb);
01851       if ( img && v )
01852          img->SetImage( infoImage.getBaseSurface(), false );
01853 
01854    }
01855 
01856    if ( container->baseType->infoImageSmallFilename.length() > 0 )
01857       setImage( "Container3DImageSmall", container->baseType->infoImageSmallFilename );
01858    
01859 
01860 
01861    setLabelText( "UnitName", cb->getName() );
01862    if ( cb->getName() != cb->baseType->name )
01863       setLabelText( "UnitClass", cb->baseType->name );
01864 
01865    NewGuiHost::pushIconHandler( &guiIconHandler );
01866 
01867    activate_i(0);
01868    cargoChanged();
01869    Show();
01870    setupOK = true;
01871 
01872 };
01873 
01874 
01875 void CargoDialog::userHandler( const ASCString& label, PropertyReadingContainer& pc, PG_Widget* parent, WidgetParameters widgetParams )
01876 {
01877    if ( label == "ButtonPanel" ) {
01878       int x = 0;
01879       int y = 0;
01880       for ( int i = 0; i < activesubwindows.size(); ++i ) {
01881          SubWinButton* button = new SubWinButton( parent, SPoint( x, y ), activesubwindows[i] );
01882          button->sigClick.connect( SigC::bind( SigC::slot( *this, &CargoDialog::activate_i  ), i));
01883          if ( x + 2*SubWinButton::buttonwidth < parent->Width() )
01884             x += SubWinButton::buttonwidth;
01885          else {
01886             x = 0;
01887             y += SubWinButton::buttonheight;
01888          }
01889          subWinButtons.push_back( button );
01890       }
01891    }
01892 
01893    if ( label == "ResourceTable" ) {
01894       int gap = 2;
01895       int cellwidth = (parent->Width() - 8 * gap) / 9;
01896       int cellHeight = (parent->Height() - 3 * gap ) / 4;
01897       for ( int x = 0; x < 9; ++x )
01898          for ( int y = 0; y < 4; ++y ) {
01899             PG_Rect r ( x * parent->Width() / 9, y * parent->Height() / 4, cellwidth, cellHeight );
01900             PG_Label* l = new PG_Label ( parent, r, PG_NULLSTR );
01901             widgetParams.assign( l );
01902             ASCString label = "Res";
01903             char xx = 'A' + x;
01904             char yy = '1' + y;
01905             label += xx;
01906             label += yy;
01907             l->SetName( label );
01908          }
01909    }
01910 
01911    if ( label == "ResearchGraph" ) {
01912       ResearchGraph* graph = new ResearchGraph( parent, PG_Rect( 0, 0, parent->Width(), parent->Height() ), container );
01913       graph->sigChange.connect( SigC::slot( *researchWindow, &SubWindow::update ));
01914    }
01915 
01916    if ( label == "MiningGraph" ) {
01917       MiningGraph* mg = new MiningGraph( parent, PG_Rect( 0, 0, parent->Width(), parent->Height() ), container );
01918       new PG_ToolTipHelp( mg, "Horizontal: distance from building ; vertical: amount of resources(M/F)");
01919 
01920    }
01921 
01922    if ( label == "DamageBar" ) {
01923       DamageBarWidget* dbw = new DamageBarWidget( parent, PG_Rect( 0, 0, parent->Width(), parent->Height() ), container );
01924       buildingControlWindow->damageChanged.connect( SigC::slot( *dbw, &DamageBarWidget::repaint ));
01925    }
01926 
01927    if ( label == "ScrollArea" ) {
01928       PG_Widget* unitScrollArea = parent;
01929       if ( unitScrollArea ) {
01930          cargoWidget = new CargoWidget( unitScrollArea, PG_Rect( 1, 1, unitScrollArea->Width() -2 , unitScrollArea->Height() -2 ), container, false );
01931          cargoWidget->enableDragNDrop( true );
01932          cargoWidget->sigDragDone.connect( SigC::slot( *this, &CargoDialog::dragUnitToInnerContainer ));
01933          cargoWidget->sigDragAvail.connect( SigC::slot( *this, &CargoDialog::dragUnitToInnerContainerAvail ));
01934          cargoWidget->sigDragInProcess.connect( SigC::slot( *this, &CargoDialog::dragInProcess ));
01935          cargoWidget->sigDragAborted.connect( SigC::slot( *this, &CargoDialog::dragAborted ));
01936 
01937          vector<StoringPosition*> storingPositionVector;
01938 
01939          int x = 0;
01940          int y = 0;
01941 
01942          int posNum = container->baseType->maxLoadableUnits;
01943          if ( container->getCargo().size() > posNum )
01944             posNum = container->getCargo().size();
01945 
01946          int unitColumnCount = 0;
01947          for ( int i = 0; i < posNum; ++i ) {
01948             pc.openBracket( "UnitSlot" );
01949 
01950             int unitposx, unitposy;
01951             pc.addInteger( "unitposx", unitposx );
01952             pc.addInteger( "unitposy", unitposy );
01953 
01954             StoringPosition* sp = new StoringPosition( cargoWidget, PG_Point( x, y), PG_Point(unitposx, unitposy), cargoWidget->getHighLightingManager(), container->getCargo(), i, container->baseType->maxLoadableUnits >= container->getCargo().size(), cargoWidget );
01955             storingPositionVector.push_back( sp );
01956             x += sp->Width();
01957             if ( x + sp->Width() >= parent->Width() - 20 ) {
01958                if ( !unitColumnCount )
01959                   unitColumnCount = i + 1;
01960                x = 0;
01961                y += sp->Height();
01962             }
01963 
01964 
01965             widgetParams.runTextIO( pc );
01966             parsePanelASCTXT( pc, sp, widgetParams );
01967             pc.closeBracket();
01968 
01969          }
01970 
01971          cargoWidget->registerStoringPositions( storingPositionVector, unitColumnCount );
01972          cargoWidget->sigScrollTrack.connect( SigC::slot( *this, &CargoDialog::clearSmallIcons ));
01973 
01974          cargoWidget->unitMarked.connect( SigC::slot( *this, &CargoDialog::checkStoringPosition ));
01975          
01976          if ( ciw )
01977             cargoWidget->unitMarked.connect( SigC::hide<Vehicle*>( SigC::slot( *ciw, &CargoInfoWindow::update )));
01978          
01979          if ( mainScreenWidget && mainScreenWidget->getGuiHost() )
01980             cargoWidget->unitMarked.connect( SigC::hide<Vehicle*>( SigC::slot( *this, &CargoDialog::clearSmallIcons )));
01981 
01982          cargoWidget->unitClicked.connect ( SigC::slot( *this, &CargoDialog::onUnitClick ));
01983 
01984          container->cargoChanged.connect( SigC::slot( *cargoWidget, &CargoWidget::redrawAll ));
01985       }
01986    }
01987    if ( label == "UnitTypeList"  || label == "UnitTypeListHorizontal" )  {
01988       int y = 0;
01989       int x = 0;
01990       parent->SetTransparency(255);
01991       for ( int i = 0; i < cmovemalitypenum; ++i ) {
01992          if ( container->baseType->vehicleCategoriesStorable & (1<<i)) {
01993             PG_Image* img = new PG_Image( parent, PG_Point(x, y),IconRepository::getIcon(moveMaliTypeIcons[i] ).getBaseSurface(), false);
01994             new PG_ToolTipHelp( img, cmovemalitypes[i] );
01995             if ( label == "UnitTypeList" )
01996                y += img->Height();
01997             
01998             if ( label == "UnitTypeListHorizontal" )
01999                x += img->Width();
02000          }
02001       }
02002 
02003    }
02004 
02005 };
02006 
02007 
02008 //*****************************************************************************************************
02009 //*****************************************************************************************************
02010 //
02011 //  GUI FUNCTIONS
02012 //
02013 //*****************************************************************************************************
02014 //*****************************************************************************************************
02015 
02016 
02017 
02018 
02019 
02020 
02021 namespace CargoGuiFunctions
02022 {
02023 
02024 
02025 bool Movement::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02026 {
02027    return ( key->keysym.sym == SDLK_SPACE );
02028 };
02029 
02030 Surface& Movement::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02031 {
02032    return IconRepository::getIcon("movement.png");
02033 };
02034 ASCString Movement::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02035 {
02036    return "move unit";
02037 };
02038 
02039 bool Movement::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02040 {
02041    Vehicle* unit = dynamic_cast<Vehicle*>(subject);
02042    if ( unit && unit->getOwner() == unit->getMap()->actplayer )
02043       return unit->canMove();
02044    return false;
02045 }
02046 
02047 void Movement::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02048 {
02049    if ( !mainScreenWidget )
02050       return;
02051 
02052    Vehicle* unit = dynamic_cast<Vehicle*>(subject);
02053    if ( !unit )
02054       return;
02055 
02056    int mode = 0;
02057    if ( isKeyPressed( SDLK_LSHIFT ) ||  isKeyPressed( SDLK_RSHIFT )) 
02058       mode |= MoveUnitCommand::DisableHeightChange | MoveUnitCommand::LimitVerticalDirection;
02059 
02060 
02061    MoveUnitCommand* move = new MoveUnitCommand( unit );
02062 
02063    ActionResult res = move->searchFields (-1, mode);
02064    if ( !res.successful() ) {
02065       dispmessage2 ( res.getCode(), NULL );
02066       delete move;
02067       return;
02068    }
02069 
02070    for ( set<MapCoordinate3D>::const_iterator i = move->getReachableFields().begin(); i != move->getReachableFields().end(); ++i )
02071       unit->getMap()->getField( *i)->a.temp = 1;
02072 
02073    for ( set<MapCoordinate3D>::const_iterator i = move->getReachableFieldsIndirect().begin(); i != move->getReachableFieldsIndirect().end(); ++i )
02074       unit->getMap()->getField( *i)->a.temp2 = 2;
02075 
02076    repaintMap();
02077    NewGuiHost::pendingCommand = move;
02078 
02079    GuiIconHandler guiIconHandler;
02080    guiIconHandler.registerUserFunction( new MovementDestination( *mainScreenWidget ) );
02081    guiIconHandler.registerUserFunction( new CancelMovement( *mainScreenWidget ) );
02082 
02083    NewGuiHost::pushIconHandler( &guiIconHandler );
02084 
02085    parent.Hide();
02086 
02087    mainScreenWidget->Update();
02088    mainScreenWidget->RunModal();
02089    parent.getMap()->cleartemps(7);
02090 
02091    NewGuiHost::popIconHandler();
02092    parent.cargoChanged();
02093    parent.Show();
02094 
02095 }
02096 
02097 
02099 
02100 
02101 bool UnitProduction::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02102 {
02103    if ( parent.getContainer()->getOwner() == parent.getContainer()->getMap()->actplayer )
02104       return ConstructUnitCommand::internalConstructionAvail( parent.getContainer() );
02105 
02106    return false;
02107 }
02108 
02109 
02110 bool UnitProduction::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02111 {
02112    return ( key->keysym.sym == 'p' );
02113 };
02114 
02115 Surface& UnitProduction::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02116 {
02117    return IconRepository::getIcon("unitproduction.png");
02118 };
02119 ASCString UnitProduction::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02120 {
02121    return "produce unit";
02122 };
02123 
02124 void UnitProduction::productionLinesChanged()
02125 {
02126    if (constructUnitCommand ) {
02127       producables.clear();
02128       ConstructUnitCommand::Producables temp = constructUnitCommand->getProduceableVehicles();
02129       producables.insert( producables.end(), temp.begin(), temp.end () );
02130    }
02131 }
02132 
02133 void UnitProduction::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02134 {
02135    bool refillAmmo;
02136    bool refillResources;
02137 
02138    auto_ptr<ConstructUnitCommand> production ( new ConstructUnitCommand( parent.getContainer() ));
02139    constructUnitCommand = production.get();
02140 
02141    const VehicleType* v;
02142    {
02143       production->setMode( ConstructUnitCommand::internal );
02144       producables = production->getProduceableVehicles();
02145       VehicleProduction_SelectionWindow fsw( NULL, PG_Rect( 10, 10, 450, 550 ), parent.getContainer(), producables, true );
02146       fsw.reloadProducebles.connect( SigC::slot( *this, &UnitProduction::productionLinesChanged ));
02147       fsw.SetTransparency(0);
02148       fsw.Show();
02149       fsw.RunModal();
02150       v = fsw.getVehicletype();
02151       refillAmmo = fsw.fillWithAmmo();
02152       refillResources = fsw.fillWithResources();
02153    }
02154    if ( v ) {
02155 
02156       for ( ConstructUnitCommand::Producables::const_iterator i = producables.begin(); i != producables.end(); ++i )
02157          if ( i->type == v ) {
02158             if ( i->prerequisites.getValue() & ( ConstructUnitCommand::Lack::Energy  | ConstructUnitCommand::Lack::Material | ConstructUnitCommand::Lack::Fuel )) {
02159                warningMessage("Not enough resources to build unit");
02160                return;
02161             }
02162 
02163             if ( i->prerequisites.getValue() & ( ConstructUnitCommand::Lack::Movement )) {
02164                warningMessage("Not enough movement to build unit");
02165                return;
02166             }
02167 
02168             if ( i->prerequisites.getValue() & ( ConstructUnitCommand::Lack::Research )) {
02169                warningMessage("This unit has not been researched yet");
02170                return;
02171             }
02172          }
02173 
02174       production->setVehicleType( v );
02175       ActionResult res = production->execute ( createContext( parent.getContainer()->getMap() ) );
02176 
02177       if ( !res.successful() )
02178          throw res;
02179 
02180       production.release();
02181 
02182       Vehicle* newUnit = constructUnitCommand->getProducedUnit();
02183       if ( !newUnit )
02184          throw ActionResult( 21804 );
02185 
02186 
02187       if ( refillAmmo || refillResources ) {
02188          auto_ptr<ServiceCommand> ser ( new ServiceCommand( parent.getContainer() ));
02189          ser->setDestination( newUnit );
02190          TransferHandler& trans = ser->getTransferHandler();
02191          if ( refillAmmo )
02192             trans.fillDestAmmo();
02193 
02194          if ( refillResources )
02195             trans.fillDestResource();
02196 
02197          ser->saveTransfers();
02198          ActionResult res = ser->execute( createContext(  newUnit->getMap() ));
02199          if ( res.successful() )
02200             ser.release();
02201          else
02202             displayActionError(res);
02203 
02204       }
02205       if ( CGameOptions::Instance()->unitProduction.fillAmmo != refillAmmo ) {
02206          CGameOptions::Instance()->unitProduction.fillAmmo = refillAmmo;
02207          CGameOptions::Instance()->setChanged();
02208       }
02209       if ( CGameOptions::Instance()->unitProduction.fillResources != refillResources ) {
02210          CGameOptions::Instance()->unitProduction.fillResources = refillResources;
02211          CGameOptions::Instance()->setChanged();
02212       }
02213 
02214    }
02215    parent.cargoChanged(); // we need to update the resources because new production lines may have been build
02216    constructUnitCommand = NULL;
02217 }
02218 
02219 
02221 
02222 
02223 bool UnitTraining::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02224 {
02225    if ( !subject )
02226       return false;
02227 
02228    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02229    if ( !veh )
02230       return false;
02231 
02232    GameMap* map = parent.getContainer()->getMap();
02233    if ( map->actplayer == veh->getOwner() || map->actplayer == parent.getContainer()->getOwner() )
02234       if ( map->player[map->actplayer].diplomacy.isAllied( veh->getOwner() ))
02235          return TrainUnitCommand::avail( parent.getContainer(), veh);
02236 
02237    return false;
02238 }
02239 
02240 
02241 bool UnitTraining::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02242 {
02243    return ( key->keysym.sym == 't' );
02244 };
02245 
02246 Surface& UnitTraining::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02247 {
02248    return IconRepository::getIcon("training.png");
02249 };
02250 
02251 ASCString UnitTraining::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02252 {
02253    return "train unit";
02254 };
02255 
02256 
02257 void UnitTraining::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02258 {
02259    if ( !subject )
02260       return;
02261 
02262    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02263    if ( !veh )
02264       return;
02265 
02266    auto_ptr<TrainUnitCommand> tuc ( new TrainUnitCommand( parent.getContainer() ));
02267    tuc->setUnit( veh );
02268    ActionResult res = tuc->execute( createContext( veh->getMap()));
02269    if ( res.successful() ) {
02270       tuc.release();
02271       parent.cargoChanged();
02272    } else
02273       displayActionError( res );
02274 }
02275 
02276 
02279 
02280 
02281 bool RefuelUnitCommand::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02282 {
02283    if ( !subject )
02284       return false;
02285 
02286    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02287    if ( !veh )
02288       return false;
02289 
02290    ServiceCommand sc( parent.getContainer() );
02291    const ServiceTargetSearcher::Targets& dest  = sc.getDestinations();
02292 
02293    return find( dest.begin(), dest.end(), subject )  != dest.end();
02294 }
02295 
02296 
02297 bool RefuelUnitCommand::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02298 {
02299    return ( key->keysym.sym == 'f' );
02300 };
02301 
02302 Surface& RefuelUnitCommand::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02303 {
02304    return IconRepository::getIcon("refuel.png");
02305 };
02306 
02307 ASCString RefuelUnitCommand::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02308 {
02309    return "refuel unit";
02310 };
02311 
02312 
02313 void RefuelUnitCommand::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02314 {
02315    if ( !subject )
02316       return;
02317 
02318    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02319    if ( !veh )
02320       return;
02321 
02322    auto_ptr<ServiceCommand> ser ( new ServiceCommand( parent.getContainer() ));
02323    ser->setDestination( subject );
02324    ser->getTransferHandler().fillDest();
02325    ser->saveTransfers();
02326    ActionResult res = ser->execute( createContext(  subject->getMap() ));
02327    if ( res.successful() )
02328       ser.release();
02329    else
02330       displayActionError(res);
02331    parent.cargoChanged();
02332 }
02334 
02335 bool RepairUnit::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02336 {
02337    if ( !subject )
02338       return false;
02339 
02340    if ( !RepairUnitCommand::availInternally( parent.getContainer() ) )
02341       return false;
02342 
02343    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02344    if ( !veh )
02345       return false;
02346 
02347 
02348    return veh->damage > 0;
02349 }
02350 
02351 
02352 bool RepairUnit::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02353 {
02354    return ( key->keysym.sym == 'r' );
02355 };
02356 
02357 Surface& RepairUnit::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02358 {
02359    return IconRepository::getIcon("repair.png");
02360 };
02361 
02362 ASCString RepairUnit::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02363 {
02364    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02365    if ( veh && parent.getContainer() ) {
02366       Resources r;
02367       parent.getContainer()->getMaxRepair ( veh, 0, r);
02368       return "~r~epair unit (cost: " + r.toString() + ")";
02369    }
02370 
02371    return "repair unit";
02372 };
02373 
02374 
02375 void RepairUnit::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02376 {
02377    if ( !subject )
02378       return;
02379 
02380    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02381    if ( !veh )
02382       return;
02383 
02384    auto_ptr<RepairUnitCommand> rp ( new RepairUnitCommand( parent.getContainer() ));
02385 
02386    if ( !rp->validTarget( veh ) )
02387       return;
02388 
02389    rp->setTarget( veh );
02390    ActionResult res = rp->execute( createContext ( veh->getMap() ));
02391    if ( res.successful() )
02392       rp.release();
02393 
02394    parent.cargoChanged();
02395 }
02396 
02398 
02399 bool MoveUnitUp::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02400 {
02401    if ( !subject )
02402       return false;
02403 
02404    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02405    if ( !veh )
02406       return false;
02407 
02408    return CargoMoveCommand::moveOutAvail( veh );
02409 }
02410 
02411 
02412 bool MoveUnitUp::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02413 {
02414    return ( key->keysym.sym == 'o' );
02415 };
02416 
02417 Surface& MoveUnitUp::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02418 {
02419    return IconRepository::getIcon("moveunitup.png");
02420 };
02421 
02422 ASCString MoveUnitUp::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02423 {
02424    return "move unit to ~o~uter transport";
02425 };
02426 
02427 
02428 void MoveUnitUp::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02429 {
02430    if ( !subject )
02431       return;
02432 
02433 
02434    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02435    if ( !veh )
02436       return;
02437 
02438    auto_ptr<CargoMoveCommand> cargomove ( new CargoMoveCommand( veh ));
02439    cargomove->setMode( CargoMoveCommand::moveOutwards );
02440    ActionResult res = cargomove->execute ( createContext( veh->getMap() ));
02441    if ( res.successful() )
02442       cargomove.release();
02443 
02444    parent.cargoChanged();
02445 }
02446 
02448 
02449 
02450 bool CloseDialog::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02451 {
02452    return true;
02453 }
02454 
02455 
02456 bool CloseDialog::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02457 {
02458    return ( key->keysym.sym == 'x' );
02459 };
02460 
02461 Surface& CloseDialog::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02462 {
02463    return IconRepository::getIcon("closecargodialog.png");
02464 };
02465 
02466 ASCString CloseDialog::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02467 {
02468    return "close dialog";
02469 };
02470 
02471 
02472 void CloseDialog::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02473 {
02474    parent.QuitModal();
02475 }
02476 
02478 
02479 
02480 bool UnitInfo::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02481 {
02482    if ( !subject )
02483       return false;
02484 
02485    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02486    return veh;
02487 }
02488 
02489 
02490 bool UnitInfo::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02491 {
02492    return ( key->keysym.sym == 'i' );
02493 };
02494 
02495 Surface& UnitInfo::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02496 {
02497    return IconRepository::getIcon("unitinfo.png");
02498 };
02499 
02500 ASCString UnitInfo::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02501 {
02502    return "show unit ~i~nformation";
02503 };
02504 
02505 
02506 void UnitInfo::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02507 {
02508    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02509    if ( veh )
02510       unitInfoDialog( veh->typ );
02511 }
02512 
02514 
02515 
02516 bool TransferUnitControl::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02517 {
02518    if ( !subject )
02519       return false;
02520 
02521    if ( subject->getOwner() != subject->getMap()->actplayer )
02522       return false;
02523 
02524    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02525    if ( !veh )
02526       return false;
02527 
02528    return TransferControlCommand::avail( subject );
02529 
02530 }
02531 
02532 
02533 Surface& TransferUnitControl::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02534 {
02535    return IconRepository::getIcon("transferunitcontrol.png");
02536 };
02537 
02538 ASCString TransferUnitControl::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02539 {
02540    return "transfer unit control";
02541 };
02542 
02543 
02544 void TransferUnitControl::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02545 {
02546    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02547    if ( veh ) {
02548 
02549       auto_ptr<TransferControlCommand> tcc ( new TransferControlCommand( subject ));
02550       TransferControlCommand::Receivers rec = tcc->getReceivers();
02551 
02552       vector<ASCString> entries;
02553       for ( TransferControlCommand::Receivers::iterator i = rec.begin(); i != rec.end(); ++i )
02554          entries.push_back ( (*i)->getName() );
02555 
02556       if ( !entries.size() ) {
02557          infoMessage("you don't have any allies!");
02558          return;
02559       }
02560 
02561       int result = chooseString ( "Choose player", entries );
02562       if ( result >= 0 ) {
02563          tcc->setReceiver( rec[result] );
02564          ActionResult res = tcc->execute( createContext( subject->getMap() ));
02565          if ( res.successful() ) {
02566             tcc.release();
02567             parent.cargoChanged();
02568          } else
02569             displayActionError( res );
02570       }
02571 
02572 
02573    }
02574 }
02575 
02577 
02578 
02579 
02580 bool MoveUnitIntoInnerContainer::available( const MapCoordinate& pos, ContainerBase* subject, int num )
02581 {
02582    if ( !subject )
02583       return false;
02584 
02585    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02586    if ( !veh )
02587       return false;
02588 
02589    CargoMoveCommand cmc( veh );
02590    return cmc.getTargetCarriers().size() > 0 ;
02591 }
02592 
02593 
02594 bool MoveUnitIntoInnerContainer::checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02595 {
02596    return ( key->keysym.sym == 'u' );
02597 };
02598 
02599 Surface& MoveUnitIntoInnerContainer::getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02600 {
02601    return IconRepository::getIcon("container-in.png");
02602 };
02603 
02604 ASCString MoveUnitIntoInnerContainer::getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02605 {
02606    return "move ~u~nit into neighboring transport";
02607 };
02608 
02609 
02610 
02611 class VehicleWidget: public VehicleBaseWidget
02612 {
02613    private:
02614       Vehicle* veh;
02615    public:
02616       VehicleWidget( PG_Widget* parent, const PG_Point& pos, int width, Vehicle* unit )
02617             : VehicleBaseWidget( parent, pos, width, unit, unit->getMap()->getPlayer(unit) ) {
02618          veh = unit;
02619       };
02620 
02621       Vehicle* getUnit() const {
02622          return veh;
02623       };
02624 };
02625 
02626 class VehicleSelectionFactory: public SelectionItemFactory, public SigC::Object
02627 {
02628    public:
02629       typedef vector<Vehicle*> Container;
02630    protected:
02631       Container::iterator it;
02632       Container& items;
02633 
02634    public:
02635       VehicleSelectionFactory( Container& units ) : items ( units ), selected(NULL) {};
02636       void restart() {
02637          it = items.begin();
02638       };
02639 
02640       SelectionWidget* spawnNextItem( PG_Widget* parent, const PG_Point& pos ) {
02641          if ( it != items.end() ) {
02642             Vehicle* v = *(it++);
02643             return new VehicleWidget( parent, pos, parent->Width() - 15, v );
02644          } else
02645             return NULL;
02646       };
02647 
02648       void itemSelected( const SelectionWidget* widget, bool mouse ) {
02649          if ( !widget )
02650             return;
02651 
02652          const VehicleWidget* vw = dynamic_cast<const VehicleWidget*>(widget);
02653          assert( vw );
02654          selected = vw->getUnit();
02655       }
02656 
02657       Vehicle* selected;
02658 };
02659 
02660 
02661 Vehicle* selectVehicle( vector<Vehicle*> targets )
02662 {
02663    Vehicle* target = NULL;
02664    VehicleSelectionFactory* vsf = new VehicleSelectionFactory( targets );
02665    ItemSelectorWindow isw ( NULL, PG_Rect( 50, 50, 300, 400), "Please choose target unit", vsf );
02666    isw.Show();
02667    isw.RunModal();
02668    target = vsf->selected;
02669    return target;
02670 }
02671 
02672 
02673 
02674 
02675 void MoveUnitIntoInnerContainer::execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02676 {
02677    if ( !subject )
02678       return;
02679 
02680 
02681    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02682    if ( !veh )
02683       return;
02684 
02685    auto_ptr<CargoMoveCommand> cargomove ( new CargoMoveCommand( veh ));
02686    cargomove->setMode( CargoMoveCommand::moveInwards );
02687 
02688    vector<Vehicle*> targets = cargomove->getTargetCarriers();
02689 
02690    choiceDialog("You can also use Drag'n'Drop to move units in the Cargo Dialog\nMouse button: " + CGameOptions::Mouse::getButtonName( CGameOptions::Instance()->mouse.dragndropbutton ), "OK", "", "dragndropinfo");
02691 
02692    Vehicle* target = selectVehicle( targets );
02693    if ( target ) {
02694       cargomove->setTargetCarrier( target );
02695       ActionResult res = cargomove->execute ( createContext( veh->getMap() ));
02696       if ( res.successful() )
02697          cargomove.release();
02698    }
02699    parent.cargoChanged();
02700 }
02701 
02702 
02703 
02705 
02706 bool RefuelUnitDialogCommand :: available( const MapCoordinate& pos, ContainerBase* subject, int num )
02707 {
02708    if ( !subject )
02709       return false;
02710 
02711    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02712    if ( !veh )
02713       return false;
02714 
02715    ServiceCommand sc( parent.getContainer() );
02716    const ServiceTargetSearcher::Targets& dest  = sc.getDestinations();
02717 
02718    return find( dest.begin(), dest.end(), subject )  != dest.end();
02719 };
02720 
02721 void RefuelUnitDialogCommand :: execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02722 {
02723    if ( !subject )
02724       return;
02725 
02726    auto_ptr<ServiceCommand> ser ( new ServiceCommand( parent.getContainer() ));
02727    ser->setDestination( subject );
02728    ammoTransferWindow( parent.getContainer(), subject, ser.get() );
02729    parent.cargoChanged();
02730    if ( ser->getState() == Command::Finished )
02731       ser.release();
02732 }
02733 
02734 Surface& RefuelUnitDialogCommand :: getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02735 {
02736    return IconRepository::getIcon("refuel-dialog.png");
02737 };
02738 
02739 bool RefuelUnitDialogCommand :: checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02740 {
02741    return ( key->keysym.unicode == 'd' );
02742 };
02743 
02744 ASCString RefuelUnitDialogCommand :: getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02745 {
02746    return "Refuel Dialog";
02747 };
02748 
02750 
02751 bool OpenContainer :: available( const MapCoordinate& pos, ContainerBase* subject, int num )
02752 {
02753    if ( !subject )
02754       return false;
02755 
02756    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02757    if ( !veh )
02758       return false;
02759 
02760    Player& player = veh->getMap()->player[veh->getOwner()];
02761    if ( veh->typ->maxLoadableUnits && player.diplomacy.isAllied( veh->getMap()->actplayer)  )
02762       return true;
02763 
02764    return false;
02765 };
02766 
02767 void OpenContainer :: execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02768 {
02769    if ( !subject )
02770       return;
02771 
02772    cargoDialog( subject );
02773    parent.cargoChanged();
02774 }
02775 
02776 Surface& OpenContainer :: getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02777 {
02778    return IconRepository::getIcon("container.png");
02779 };
02780 
02781 bool OpenContainer :: checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02782 {
02783    return ( key->keysym.unicode == 'l' );
02784 };
02785 
02786 ASCString OpenContainer :: getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02787 {
02788    return "open transport ";
02789 };
02790 
02791 
02792 
02793 
02795 
02796 
02797 bool RecycleUnitCommandButton :: available( const MapCoordinate& pos, ContainerBase* subject, int num )
02798 {
02799    if ( !subject )
02800       return false;
02801 
02802    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02803    if ( !veh )
02804       return false;
02805 
02806    if ( !RecycleUnitCommand::avail( parent.getContainer(), veh))
02807       return false;
02808 
02809    Player& player = veh->getMap()->player[veh->getOwner()];
02810    if ( player.diplomacy.isAllied( veh->getMap()->actplayer)  )
02811       return true;
02812    else
02813       return false;
02814 };
02815 
02816 ASCString RecycleUnitCommandButton :: getCommandName( const ContainerBase* carrier )
02817 {
02818    if ( carrier->baseType->hasFunction( ContainerBaseType::RecycleUnits ))
02819       return "recycle";
02820    else
02821       return "salvage";
02822 }
02823 
02824 
02825 void RecycleUnitCommandButton :: execute( const MapCoordinate& pos, ContainerBase* subject, int num )
02826 {
02827    if ( !subject )
02828       return;
02829 
02830    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02831    if ( !veh )
02832       return;
02833 
02834    ASCString msg = "do you really want to " + getCommandName( parent.getContainer() ) + " this unit ?";
02835 
02836    if (choice_dlg( msg ,"~y~es","~n~o") == 1) {
02837       auto_ptr<RecycleUnitCommand> command ( new RecycleUnitCommand( parent.getContainer() ));
02838       command->setUnit( veh );
02839       ActionResult res = command->execute( createContext( parent.getContainer()->getMap() ));
02840       if ( res.successful() )
02841          command.release();
02842       else
02843          displayActionError( res );
02844       parent.cargoChanged();
02845    }
02846 }
02847 
02848 
02849 Surface& RecycleUnitCommandButton :: getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
02850 {
02851    return IconRepository::getIcon("recycle.png");
02852 };
02853 
02854 bool RecycleUnitCommandButton :: checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
02855 {
02856    return false;
02857 };
02858 
02859 ASCString RecycleUnitCommandButton :: getName( const MapCoordinate& pos, ContainerBase* subject, int num )
02860 {
02861    if ( !subject )
02862       return "";
02863 
02864    Vehicle* veh = dynamic_cast<Vehicle*>(subject);
02865    if ( !veh )
02866       return "";
02867 
02868    ASCString s = getCommandName( parent.getContainer() ) + " unit - ";
02869 
02870    Resources res = RecycleUnitCommand::getOutput( parent.getContainer(), veh );
02871 
02872    bool cost = false;
02873    for ( int r = 0; r < 3; ++r ) {
02874       if ( res.resource(r) < 0 ) {
02875          if ( !cost ) {
02876             s += "Cost: ";
02877             cost = true;
02878          }
02879          s += ASCString::toString( -res.resource( r ));
02880          s += " ";
02881          s += Resources::name( r );
02882       }
02883    }
02884 
02885    bool gain = false;
02886    for ( int r = 0; r < 3; ++r ) {
02887       if ( res.resource(r) > 0 ) {
02888          if ( !gain ) {
02889             s += "Gain: ";
02890             cost = true;
02891          }
02892          s += ASCString::toString( res.resource( r ));
02893          s += " ";
02894          s += Resources::name( r );
02895       }
02896    }
02897 
02898    return s;
02899 
02900 };
02901 
02902 }
02903 

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