00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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