///我将此注释移到顶部:我正在使用结构和相关方法(如int MyClass_getInt(MyClass * this))重新创建OOP
我正在用C编写一个小型DAW。在Timeline.h中有我的时间轴和 Region 类。我希望我的 UndoRedoStack 类能够与多个 Timeline 实例一起使用,所以我希望 UndoRedoStack 位于单独的.c中/.h文件。
这种思路似乎要求 TimelineUndoRedoCommand 类了解时间轴和区域,因为它需要备份先前存在的状态。
还需要时间轴来了解 TimelineUndoRedoCommand ,以便可以将它们触发到 UndoRedoStack 中。
这似乎是循环依赖。我应该如何构造它们,以便避免循环依赖?
// 我最终要求Timeline.h编写所有需要它的代码,但是像这样单独存放UndoRedo:
/*
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);
}