#include "ET++.ph" #ifdef __GNUG__ #pragma implementation #endif #include "CommandProcessor.h" #include "Class.h" #include "Command.h" #include "ObjArray.h" #include "Menu.h" #include "CmdNo.h" //---- CommandProcessor -------------------------------------------------------- NewMetaImpl(CommandProcessor,RefCounted, (T(changeCount), T(cap))); CommandProcessor::CommandProcessor() { cap= changeCount= 0; } CommandProcessor::~CommandProcessor() { //if (changeCount > 0) // Error("~CommandProcessor", "changeCount > 0"); } Command *CommandProcessor::GetAt(int) { return 0; } void CommandProcessor::PerformCommand(Command* cmd) { if (cmd == 0) return; switch (cmd->GetType()) { case eCmdTypeCantUndo: FinishFrom(0); changeCount+= cmd->Perform(); Changed(); cmd->Done(0); cmd->Finish(); break; case eCmdTypeNoChange: CommandProcessor::PerformNormalCommand(cmd); break; case eCmdTypeNormal: FinishFrom(changeCount); PerformNormalCommand(cmd); break; } } void CommandProcessor::PerformNormalCommand(Command* cmd) { if (cmd) { cmd->Perform(); cmd->Done(0); cmd->Finish(); } } void CommandProcessor::DoCreateMenu(Menu *menu) { if (menu->GetId() == cEDITMENU) { if (Size() <= 0) menu->AppendItems("Can't undo2", cUNDO, 0); else { menu->AppendItem("Undo2@Z", cUNDO); if (Size() >= 2) menu->AppendItems("Redo2@Z", cREDO, 0); } } } void CommandProcessor::DoSetupMenu(Menu *menu) { if (menu->GetId() == cEDITMENU) { Command *cmd; if (cmd= GetAt(changeCount-1)) { menu->ReplaceItem(cUNDO, cmd->GetUndoName()); if (cmd->GetType() != eCmdTypeCantUndo) menu->EnableItem(cUNDO); } else { menu->ReplaceItem(cUNDO, "Undo@Z"); menu->DisableItem(cUNDO); } if (Size() >= 2) { if (cmd= GetAt(changeCount)) { menu->ReplaceItem(cREDO, cmd->GetUndoName()); menu->EnableItem(cREDO); } else { menu->ReplaceItem(cREDO, "Redo@Z"); menu->DisableItem(cREDO); } } } } void CommandProcessor::DoMenuCommand(int cmdId) { Command *c; switch (cmdId) { case cUNDO: if (c= GetAt(changeCount-1)) { changeCount+= c->Perform(); Changed(); } break; case cREDO: if (c= GetAt(changeCount)) { changeCount+= c->Perform(); Changed(); } break; } } void CommandProcessor::Finish() { FinishFrom(0); changeCount= 0; Changed(); } void CommandProcessor::FinishFrom(int) { } //---- SingleCommandProcessor -------------------------------------------------- NewMetaImpl(SingleCommandProcessor,CommandProcessor, (TP(lastCmd))); SingleCommandProcessor::SingleCommandProcessor() { lastCmd= 0; cap= 1; } Command *SingleCommandProcessor::GetAt(int) { return lastCmd; } void SingleCommandProcessor::PerformNormalCommand(Command* cmd) { if (lastCmd) lastCmd->Done(cmd); lastCmd= cmd; changeCount+= cmd->Perform(); Changed(); } void SingleCommandProcessor::FinishFrom(int) { if (lastCmd) { lastCmd->Finish(); lastCmd= 0; } } //---- UnboundedCommandProcessor ----------------------------------------------- NewMetaImpl(UnboundedCommandProcessor,CommandProcessor, (TP(cmdHistory))); UnboundedCommandProcessor::UnboundedCommandProcessor() { cmdHistory= new ObjArray; cap= 99999; } UnboundedCommandProcessor::~UnboundedCommandProcessor() { SafeDelete(cmdHistory); } Command *UnboundedCommandProcessor::GetAt(int i) { if (i >= 0 && i < cmdHistory->Size()) return (Command*) cmdHistory->At(i); return 0; } void UnboundedCommandProcessor::PerformNormalCommand(Command* cmd) { Command *lastcmd; if (lastcmd= GetAt(changeCount-1)) lastcmd->Done(cmd); cmdHistory->AtPutAndExpand(changeCount, cmd); changeCount+= cmd->Perform(); Changed(); } void UnboundedCommandProcessor::FinishFrom(int n) { for (int i= n; i < cmdHistory->Size(); i++) { Command *c= (Command*) cmdHistory->At(i); if (c) { c->Finish(); cmdHistory->RemoveAt(i); } } } //---- BoundedCommandProcessor ------------------------------------------------- NewMetaImpl(BoundedCommandProcessor,CommandProcessor, (TVP(mem,cap), T(start), T(size))); BoundedCommandProcessor::BoundedCommandProcessor(int s) { cap= s; mem= new Command* [cap]; size= start= 0; } BoundedCommandProcessor::~BoundedCommandProcessor() { SafeDelete(mem); } Command *BoundedCommandProcessor::GetAt(int i) { if (i >= start && i < start+size) return mem[i % size]; return 0; } void BoundedCommandProcessor::PerformNormalCommand(Command* cmd) { Command *lastcmd; if (size >= cap) { // overflow start++; GetAt(changeCount)->Finish(); size--; } size++; if (lastcmd= GetAt(changeCount-1)) lastcmd->Done(cmd); mem[changeCount % size]= cmd; changeCount+= cmd->Perform(); Changed(); } void BoundedCommandProcessor::FinishFrom(int n) { Command *c; n= (n == 0) ? start : changeCount; for (int i= n; c= GetAt(i); i++) c->Finish(); size-= (i-changeCount); }