PDcurses оболочку модуля, с MVC или интеллекту


Я давно пишу библиотеку оболочки для pdcurses на некоторое время и реализуется каждый виджет/класса в его идиому Pimpl, но я начинаю видеть, что для больших виджеты это создает Бог объект и, чем я узнала про паттерн MVC, и решил дать ему попробовать и реализовать простой виджет первый (флажок).

Единственная проблема у меня с шаблона MVC является то, что он требует создания 3 объекты представляют собой один виджет (объект, модель, объект, Вид, Контроллер объекта) против прыщ фразеологизм, который требует, чтобы быть созданный только 1 объект.

Так что вопрос у меня из выше: это в MVC подходит для дизайна модуля или просто дизайн приложения ? и я должен по-прежнему придерживаться прыщ идиома для написания библиотеки (DLL)?

Я добавил в код ниже, чтобы показать, что я имею в виду второй абзац (3 против 1 объекты в виджет).


Реализация MVC в

в MVC.ч:

#ifndef MVC_H
#define MVC_H

#include "curses.h"

#include "cw_types.h"

namespace cw {
    class CheckBoxData
    {
    public:
        bool state() const;
        void toggle();

    private:
        bool state_{ false };
    };

    class CheckBoxView
    {
    public:
        ~CheckBoxView();

        int  create(Position pos, chtype color_pair);
        void printCheckBoxState(bool state);
        bool clicked(MEVENT const& mevent);
        void move(Position pos);
        void clear();

    private:
        WINDOW* view_win_{ nullptr };
    };

    class CheckBoxController
    {
    public:
        CheckBoxController(CheckBoxData& data, CheckBoxView& view);

        int  create(Position pos, chtype color_pair);
        bool clicked(MEVENT const& mevent) const;
        void updateCheckBoxView();
        void move(Position pos);
        bool state() const;
        void toggle();
        void clear();

    private:
        CheckBoxData& data_;
        CheckBoxView& view_;
    };
}

#endif 

mvc.cpp:

#include "mvc.h"

#include "state_flags.h"

namespace cw {
    namespace details {
        constexpr int CHECKBOX_WIDTH { 3 };
        constexpr int CHECKBOX_HEIGHT{ 1 };
        constexpr int CENTER_X       { 1 };
        constexpr int CENTER_Y       { 0 };
    }

    bool CheckBoxData::state() const
    {
        return state_;
    }

    void CheckBoxData::toggle()
    {
        state_ ? state_ = false : state_ = true;
    }

    CheckBoxView::~CheckBoxView()
    {
        delwin(view_win_);
    }

    int CheckBoxView::create(Position pos, chtype color_pair)
    {
        if (view_win_)
            delwin(view_win_);

        if (pos.y < 0 || pos.x < 0)
            return flags::BAD_POSITION;

        view_win_ = newwin(details::CHECKBOX_HEIGHT, details::CHECKBOX_WIDTH, pos.y, pos.x);
        if (!view_win_)
            return flags::BAD_ALLOC;
        wbkgd(view_win_, color_pair);
        wprintw(view_win_, "[ ]");
        return flags::GOOD;
    }

    void CheckBoxView::printCheckBoxState(bool state)
    {
        state ? mvwaddch(view_win_, details::CENTER_Y, details::CENTER_X, 'X')
                : mvwaddch(view_win_, details::CENTER_Y, details::CENTER_X, ' ');
        wrefresh(view_win_);
    }

    bool CheckBoxView::clicked(MEVENT const& mevent)
    {
        if (!wenclose(view_win_, mevent.y, mevent.x))
            return false;
        return true;
    }

    void CheckBoxView::move(Position pos)
    {
        mvwin(view_win_, pos.y, pos.x);
    }

    void CheckBoxView::clear()
    {
        delwin(view_win_);
        view_win_ = nullptr;
    }

    CheckBoxController::CheckBoxController(CheckBoxData& data, CheckBoxView& view)
        : data_{ data }, view_{ view }
    {
    }

    int CheckBoxController::create(Position pos, chtype color_pair)
    {
        return view_.create(pos, color_pair);
    }

    bool CheckBoxController::clicked(MEVENT const & mevent) const
    {
        return view_.clicked(mevent);
    }

    void CheckBoxController::updateCheckBoxView()
    {
        view_.printCheckBoxState(data_.state());
    }

    void CheckBoxController::move(Position pos)
    {
        view_.move(pos);
    }

    bool CheckBoxController::state() const
    {
        return data_.state();
    }

    void CheckBoxController::toggle()
    {
        data_.toggle();
    }

    void CheckBoxController::clear()
    {
        view_.clear();
    }
}

Реализация интеллекту

галку.ч:

#ifndef CHECKBOX_H
#define CHECKBOX_H

#include <memory>

#include "curses.h"

#include "cw_types.h"

namespace cw {
    class CheckBox final
    {
    public:
        CheckBox();

        CheckBox(CheckBox const& checkbox) = delete;
        CheckBox(CheckBox&& checkbox);

        ~CheckBox();

        CheckBox& operator=(CheckBox const& checkbox) = delete;
        CheckBox& operator=(CheckBox&& checkbox);

        int  create(Position pos, chtype color_pair);
        bool clicked(MEVENT const& mevent) const;
        void move(Position pos);
        bool state() const;
        void toggle();
        void update();
        void clear();

    private:
        class CheckBoxImpl;
        std::unique_ptr<CheckBoxImpl> checkbox_impl_;
    };
}

#endif 

checkbox.cpp:

#include "checkbox.h"

#include "state_flags.h"

namespace cw {
    namespace details {
        constexpr int CHECKBOX_WIDTH { 3 };
        constexpr int CHECKBOX_HEIGHT{ 1 };
        constexpr int CENTER_X       { 1 };
        constexpr int CENTER_Y       { 0 };
    }

    class CheckBox::CheckBoxImpl final
    {
    public:
        ~CheckBoxImpl();

        int  create(Position pos, chtype color_pair);
        bool clicked(MEVENT const& mevent) const;
        void move(Position pos);
        bool state() const;
        void toggle();
        void update();
        void clear();

    private:
            WINDOW* checkbox_win_{ nullptr };
            bool    state_{ false };
    };

    CheckBox::CheckBox()
        : checkbox_impl_{ std::make_unique<CheckBoxImpl>() }
    {
    }

    CheckBox::CheckBox(CheckBox&& checkbox)
        : checkbox_impl_{ std::move(checkbox.checkbox_impl_) }
    {
    }

    CheckBox::~CheckBox()
    {
    }

    CheckBox& CheckBox::operator=(CheckBox&& checkbox)
    {
        if (&checkbox == this)
            return *this;

        checkbox_impl_ = std::move(checkbox.checkbox_impl_);

        return *this;
    }

    int CheckBox::create(Position pos, chtype color_pair)
    {
        return checkbox_impl_->create(pos, color_pair);
    }

    bool CheckBox::clicked(MEVENT const& mevent) const 
    {
        return checkbox_impl_->clicked(mevent);
    }

    void CheckBox::move(Position pos)
    {
        checkbox_impl_->move(pos);
    }

    bool CheckBox::state() const
    {
        return checkbox_impl_->state();
    }

    void CheckBox::toggle()
    {
        checkbox_impl_->toggle();
    }

    void CheckBox::update()
    {
        checkbox_impl_->update();
    }

    void CheckBox::clear()
    {
        checkbox_impl_->clear();
    }

    CheckBox::CheckBoxImpl::~CheckBoxImpl()
    {
        delwin(checkbox_win_);
    }

    int CheckBox::CheckBoxImpl::create(Position pos, chtype color_pair)
    {
        if(checkbox_win_)
            delwin(checkbox_win_);

        if (pos.y < 0 || pos.x < 0)
            return flags::BAD_POSITION;

        checkbox_win_ = newwin(details::CHECKBOX_HEIGHT, details::CHECKBOX_WIDTH, pos.y, pos.x);
        if (!checkbox_win_)
            return flags::BAD_ALLOC;
        wbkgd(checkbox_win_, color_pair);
        wprintw(checkbox_win_, "[ ]");
        return flags::GOOD;
    }

    bool CheckBox::CheckBoxImpl::clicked(MEVENT const& mevent) const
    {
        if (!wenclose(checkbox_win_, mevent.y, mevent.x))
            return false;
        return true;
    }

    void CheckBox::CheckBoxImpl::move(Position pos)
    {
        mvwin(checkbox_win_, pos.y, pos.x);
    }

    bool CheckBox::CheckBoxImpl::state() const
    {
        return state_;
    }

    void CheckBox::CheckBoxImpl::toggle()
    {
        state_ ? state_ = false : state_ = true;
    }

    void CheckBox::CheckBoxImpl::update()
    {
        state_ ? mvwaddch(checkbox_win_, details::CENTER_Y, details::CENTER_X, 'X')
                 : mvwaddch(checkbox_win_, details::CENTER_Y, details::CENTER_X, ' ');
        wrefresh(checkbox_win_);
    }

    void CheckBox::CheckBoxImpl::clear()
    {
        delwin(checkbox_win_);
        checkbox_win_ = nullptr;
    }
}

Например, в MVC:

#include <exception>

#include "state_flags.h"
#include "mvc.h"

int main()
{
    initscr(); 
    mousemask(BUTTON1_CLICKED, NULL);
    keypad(stdscr, TRUE);
    start_color();
    curs_set(0);
    noecho();
    raw();
    refresh();

    init_pair(1, COLOR_BLUE, COLOR_WHITE);

    try {
        cw::CheckBoxData model;
        cw::CheckBoxView view;

        MEVENT mevent;
        cw::CheckBoxController controller{ model, view };
        if (controller.create({ 10,10 }, COLOR_PAIR(1)) & cw::flags::GOOD) {
            controller.updateCheckBoxView();

            while (true) {
                if(getch() == KEY_MOUSE)
                    if(nc_getmouse(&mevent) == OK)
                        if(mevent.bstate & BUTTON1_CLICKED)
                            if (controller.clicked(mevent)) {
                                controller.toggle();
                                controller.updateCheckBoxView();
                            }
            }
        }
    }
    catch (std::exception const& e) {
        addstr(e.what());
    }

    getch();
    endwin();
    return 0;
}

Пример интеллекту:

#include <exception>

#include "state_flags.h"
#include "checkbox.h"

int main()
{
    initscr(); 
    mousemask(BUTTON1_CLICKED, NULL);
    keypad(stdscr, TRUE);
    start_color();
    curs_set(0);
    noecho();
    raw();
    refresh();

    init_pair(1, COLOR_BLUE, COLOR_WHITE);

    try {
        cw::CheckBox checkbox;
        MEVENT mevent;
        if (checkbox.create({ 10,10 }, COLOR_PAIR(1)) & cw::flags::GOOD) {
            checkbox.update();
            while (true) {
                if(getch() == KEY_MOUSE)
                    if(nc_getmouse(&mevent) == OK)
                        if(mevent.bstate & BUTTON1_CLICKED)
                            if (checkbox.clicked(mevent)) {
                                checkbox.toggle();
                                checkbox.update();
                            }
            }
        }
    }
    catch (std::exception const& e) {
        addstr(e.what());
    }

    getch();
    endwin();
    return 0;
}


Комментарии