Как мне избежать циклического кодирования зависимостей UNDO / REDO в C? - PullRequest
0 голосов
/ 24 мая 2019

// Я перемещаю эту заметку наверх: я воссоздаю ООП со структурами и связанными методами, такими как int MyClass_getInt (MyClass * this)

Я пишу небольшую DAW в C. У меня есть классы Timeline и Region в Timeline.h. Я бы хотел, чтобы мой класс 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...