mercredi 31 juillet 2019

How to implement "Job finished, delete me" action e.g. menu exit button

I was thinking of creating a menu window, that would handle all the input given, when it's open. It would hold several buttons with associated actions. I stumbled on a problem, how to implement an exit button on the menu. I can't just append it to the rest of the buttons, because the program will crash if exit button is not at the end of the iteration.

I would have to use a separate exit button and set its function in a constructor or set some sort of return so that the entity holding the menu would know it's time to close it but both ideas smell to me. Do you know how it should be solved? Is sort of 'delete this' a must here? Or is there an elegant solution. In simplified version code looks like this:

using Action = std::function<void()>;

struct Button {
    Coords xy;
    bool isPressed(Coords mouse) {
        return mouse == xy;
}

struct Menu : IContent {
    std::map <Action, Button> buttons; //Can't put exitButton here
    std::pair<Action, Button> exitButton;

void handleInput(Coords mouse) {
    for (const auto& pair : buttons)
        if (pair.second.isPressed(mouse))
            pair.first();
    if (exitButton.second.isPressed(mouse))
        exitButton.first(); //must be checked as last one
}
    Menu(Action a) :
        exitButton(std::make_pair(a, { 0, 0} ) {}
}

struct MainFrame {
    std::unique_ptr<IContent> currentContent;

    void handleInput(Coords mouse) {
        if (currentContent)
            currentContent->handleInput(mouse);
}

void popMenu() {
currentContent.reset(std::make_unique<Menu>([this]() {
    currentContent.reset(...); //Back to other content, but it's basically 
                               //delete this
}
}

//or idea with return

struct Menu {
bool isPressed(/*...*/) //always returns false, only exitButton would return 
                        //true
}

struct MainFrame { /*...*/
void handleInput(Coords mouse) {
if (currentContent->handleInput(Coords))
    /* switch menu logic */
}

Summing up, is object taking care of its own lifetime bad design?

Aucun commentaire:

Enregistrer un commentaire