//I'm moving this note to the top: I'm recreating OOP with structs and associated methods like int MyClass_getInt(MyClass* this)
I'm coding a small DAW in C. I have my Timeline and Region classes in Timeline.h. I would like my UndoRedoStack class to be able to work with multiple Timeline instances so I'd like the UndoRedoStack to be in a separate .c/.h file.
This line of thinking seems to require the TimelineUndoRedoCommand class to know about Timelines and Regions because it needs to backup pre-existing states.
It also requires Timelines to know about TimelineUndoRedoCommands so that it can fire them into the UndoRedoStack.
This seems to be a circular dependency. How should I structure this so that I can avoid circular dependencies?
// I ended up asking Timeline.h to write all the code that needs it but house the UndoRedo separately like so:
/*
UndoRedoCmd
*/
typedef struct _UndoRedoCmd{
void* content;
char* name;
}UndoRedoCmd;
/*
UndoRedoStack
*/
typedef struct _UndoRedoStack{
t_LinkList* undoStack;
t_LinkList* redoStack;
bool redoingNow;
void (*redoFunc)(UndoRedoCmd* redoThis);
void (*undoFunc)(UndoRedoCmd* undoThis);
}UndoRedoStack;
/*
UndoRedoCmd
*/
UndoRedoCmd* UndoRedoCmd_New(char* name, void* content){
UndoRedoCmd* this = malloc(sizeof(UndoRedoCmd));
this->name=name;
this->content=content;
return this;
}
void UndoRedoCmd_Kill(UndoRedoCmd* this){
/*this should never be used. instead the
user of UndoRedoStack should provide
a custom killer which simply calls
free after freeing the contents
*/
}
/*
UndoRedoStack
*/
UndoRedoStack* UndoRedoStack_New(
void (*redoFunc)(UndoRedoCmd*),
void (*undoFunc)(UndoRedoCmd*),
void (*freeLinkFunction)(void*)
){
/*
redoFunc is meant to take the content of the command and redo some action with it.
undoFunc is the opposite
freeLinkFunction is meant should free a LinkList_Link with the custom UndoRedo content inside of it.
*/
UndoRedoStack* this = malloc(sizeof(UndoRedoStack));
this->undoFunc=undoFunc;
this->redoFunc=redoFunc;
this->redoStack = LinkList_New();
this->redoStack->autoFree=2;
this->redoStack->customFree=freeLinkFunction;
this->undoStack = LinkList_New();
this->undoStack->autoFree=2;
this->undoStack->customFree=freeLinkFunction;
return this;
}
void UndoRedoStack_Kill(UndoRedoStack* this){
LinkList_Free(this->undoStack);
LinkList_Free(this->redoStack);
free(this);
}
void UndoRedoStack_do(UndoRedoStack* this,char* name,void* undoredoinfo){
UndoRedoCmd* mycmd = UndoRedoCmd_New(name, undoredoinfo);
LinkList_push(this->undoStack, mycmd);
}
void UndoRedoStack_undo(UndoRedoStack* this){
if(this->undoStack->length==0){
return;
}
UndoRedoCmd* undoMe = (UndoRedoCmd*)LinkList_pop(this->undoStack);
this->undoFunc(undoMe);
LinkList_push(this->redoStack, undoMe);
}
void UndoRedoStack_redo(UndoRedoStack* this){
if(this->redoStack->length==0){
return;
}
UndoRedoCmd* redoMe = (UndoRedoCmd*)LinkList_pop(this->redoStack);
this->redoFunc(redoMe);
LinkList_push(this->undoStack, redoMe);
}