actioncontainer.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004  
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009  
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014  
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the 
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00018      Boston, MA  02111-1307  USA
00019 */
00020 
00021 
00022 #include "actioncontainer.h"
00023 #include "../gamemap.h"
00024 
00025 #include "../util/messaginghub.h"
00026 #include "../basestrm.h"
00027 #include "../util/messaginghub.h"
00028 
00029 SigC::Signal2<void,GameMap*,const Command&> ActionContainer::postActionExecution;
00030 SigC::Signal2<void,GameMap*,Command&> ActionContainer::commitCommand;
00031 SigC::Signal1<void,GameMap*> ActionContainer::actionListChanged;
00032 
00033 
00034 ActionContainer::ActionContainer( GameMap* gamemap )
00035    : map ( gamemap )
00036 {
00037    currentPos = actions.begin(); 
00038   
00039 }
00040 
00041 void ActionContainer::add( Command* action )
00042 {
00043    for ( Actions::iterator i = currentPos; i != actions.end(); ++i )
00044       delete *i;
00045    actions.erase( currentPos, actions.end() );
00046    
00047    actions.push_back( action );
00048    currentPos = actions.end();
00049    
00050    commandState_map[action] = true;
00051    
00052    postActionExecution( map, *action );
00053    actionListChanged(map);
00054 }
00055 
00056 ActionResult ActionContainer::undo( const Context& context )
00057 {
00058    ActionResult res(0);
00059    if ( currentPos == actions.begin() )
00060       return ActionResult(23400);
00061    
00062    try {
00063       Actions::iterator a = currentPos;
00064       --a;
00065       if( isActive_map( *a ) ) {
00066          res = (*a)->undo ( context );
00067          commandState_map[*a] = false;
00068       }
00069       currentPos = a;
00070    } catch ( ActionResult result ) {
00071       errorMessage(result.getMessage());
00072       return result;
00073    }
00074    actionListChanged(map);
00075    return res;
00076 }
00077 
00078 
00079 ActionResult ActionContainer::redo( const Context& context )
00080 {
00081    ActionResult res(0);
00082    if ( currentPos == actions.end() )
00083       return res;
00084    
00085    try {
00086       res = (*currentPos)->redo( context );
00087       commandState_map[*currentPos] = true;
00088       ++currentPos;
00089    } catch ( ActionResult result ) {
00090       errorMessage(result.getMessage());
00091    }
00092    actionListChanged(map);
00093    return res;
00094 }
00095 
00096 void ActionContainer::breakUndo()
00097 {
00098    for ( Actions::iterator i = actions.begin(); i != currentPos; ++i ) {
00099       if( isActive_map( *i ) ) 
00100          commitCommand( map, **i );
00101       delete *i;
00102    }
00103    actions.clear();
00104    currentPos=actions.end();
00105    
00106    actionListChanged(map);
00107 }
00108 
00109 const int actionContainerversion = 2;
00110 
00111 void ActionContainer::read ( tnstream& stream )
00112 {
00113    int version = stream.readInt();
00114    if ( version > actionContainerversion )
00115       throw tinvalidversion ( "ActionContainer", actionContainerversion, version );
00116       
00117    int actionCount = stream.readInt();
00118    for ( int i = 0; i < actionCount; ++i ) {
00119       Command* a = dynamic_cast<Command*>( GameAction::readFromStream( stream, map ));
00120       actions.push_back ( a );
00121       
00122       if ( version >= 2 ) {
00123          commandState_map[a] = stream.readInt();
00124          
00125          int b = stream.readInt();
00126          if ( b >= 0 )
00127             commandState_map[a] = b;
00128       }
00129    }
00130    
00131    int pos = stream.readInt();
00132    currentPos = actions.begin();
00133    while ( pos-- )
00134       currentPos++;
00135    
00136    if ( version <= 1 )
00137       initCommandState( commandState_map );
00138    
00139 }
00140 
00141 
00142 void ActionContainer::write ( tnstream& stream )
00143 {
00144    stream.writeInt( actionContainerversion );
00145    
00146    stream.writeInt( actions.size() );
00147    for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
00148       (*i)->write(stream );
00149       
00150       if ( commandState_map.find( *i ) != commandState_map.end() )
00151          stream.writeInt( commandState_map[*i] );
00152       else
00153          stream.writeInt( 1 );
00154       
00155       if ( commandState_request.find( *i ) != commandState_request.end() )
00156          stream.writeInt( commandState_request[*i] );
00157       else
00158          stream.writeInt( -1 );
00159 
00160    }
00161    
00162    int counter = 0;
00163    Actions::iterator i = actions.begin();
00164    while ( i != currentPos ) {
00165       ++counter;
00166       ++i;
00167    }
00168    stream.writeInt( counter );
00169    
00170 }
00171 
00172 void ActionContainer::getActionDescriptions( vector<ASCString>& list )
00173 {
00174    list.clear();  
00175    for ( Actions::iterator i = actions.begin(); i != currentPos; ++i )
00176       list.push_back( (*i)->getDescription() );
00177 
00178 }
00179 
00180 void ActionContainer::initCommandState( CommandState& commandState )
00181 {
00182    commandState.clear();
00183    for ( Actions::iterator i = actions.begin(); i != currentPos; ++i )
00184       commandState[*i] = true;
00185    for ( Actions::iterator i = currentPos; i != actions.end(); ++i )
00186       commandState[*i] = false;
00187 }
00188 
00189 
00190 bool ActionContainer::isActive_map( const Command* action ) const
00191 {
00192    if ( commandState_map.find( action ) != commandState_map.end() )
00193       return commandState_map.find(action)->second;
00194    else {
00195       warningMessage("ActionContainer::isActive_map - invalid parameter");
00196       return false;
00197    }
00198 }
00199 
00200 bool ActionContainer::isActive_req( const Command* action ) 
00201 {
00202    if ( commandState_request.find( action ) != commandState_request.end() )
00203       return commandState_request[action];
00204    else {
00205       commandState_request = commandState_map;
00206       if ( commandState_request.find( action ) != commandState_request.end() )
00207          return commandState_request[action];
00208       else
00209          return false;
00210    }
00211 }
00212 
00213 
00214 ActionResult ActionContainer::rerun( const Context& context )
00215 {
00216    
00217    Actions::iterator currentCommand = currentPos;
00218    Actions::iterator firstDelta = currentPos;
00219    Actions::iterator i = currentPos;
00220    while ( i != actions.begin() ) {
00221       --i;
00222       if ( commandState_map.find( *i ) == commandState_map.end() )
00223          fatalError( "ActionContainer::rerun - inconsistent commandState_map ");
00224            
00225       if ( commandState_request.find( *i ) != commandState_request.end() ) {
00226          if ( commandState_request[*i] != commandState_map[*i] )
00227             firstDelta = i;
00228       }
00229    }
00230    
00231    while ( currentPos > firstDelta ) {
00232       --currentPos;
00233       if( isActive_map( *currentPos ) ) {
00234          ActionResult res = (*currentPos)->undo ( context );
00235          if ( !res.successful()) 
00236             return res;
00237       }
00238    }
00239    
00240    for ( CommandState::iterator j = commandState_request.begin(); j != commandState_request.end(); ++j )
00241       commandState_map[j->first] = j->second;
00242    
00243    commandState_request.clear();
00244    
00245    while ( currentPos < actions.end() ) {
00246       if( isActive_map( *currentPos ) ) {
00247          ActionResult res = (*currentPos)->redo ( context );
00248          if ( !res.successful()) 
00249             return res;
00250       }
00251       ++currentPos;
00252    }
00253    
00254    
00255    
00256    return ActionResult(0);
00257 }
00258 
00259 
00260 void ActionContainer::setActive( const Command* action, bool active )
00261 {
00262    if ( commandState_request.empty() )
00263       commandState_request = commandState_map;
00264    
00265    commandState_request[action] = active;
00266 }
00267 
00268 
00269 void ActionContainer::getCommands( AbstractCommandWriter& writer)
00270 {
00271    for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
00272       if ( isActive_map( *i )) {
00273          ASCString command = (*i)->getCommandString();
00274          if ( !command.empty()) {
00275             writer.printComment( (*i)->getDescription() );
00276             writer.printCommand( command );
00277          }
00278       }
00279    }
00280 }
00281 
00282 
00283 ActionContainer::~ActionContainer()
00284 {
00285    for ( Actions::iterator i = actions.begin(); i != actions.end(); ++i ) {
00286       delete *i;
00287    }
00288 }
00289 

Generated on Mon May 14 01:31:39 2012 for Advanced Strategic Command by  doxygen 1.5.1