diff --git a/orcamento.project b/orcamento.project index e0dbcd8..29a403b 100644 --- a/orcamento.project +++ b/orcamento.project @@ -112,11 +112,11 @@ - - + + @@ -135,8 +135,8 @@ - + diff --git a/presenter-test/BudgetDetailPresenter-unit.cpp b/presenter-test/BudgetDetailPresenter-unit.cpp deleted file mode 100644 index ef0629d..0000000 --- a/presenter-test/BudgetDetailPresenter-unit.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "common.hpp" -#include "stubs/BudgetControllerStub.hpp" -#include "BudgetDetailPresenter.hpp" - -class BudgetDetailFixture -{ - protected: - CallRecorder call_recorder; - nana::form host{API::make_center(800, 600)}; - nana::place placer { host }; - BudgetDetailPresenter budgetDetailPresenter{host, make_unique(call_recorder)}; - - BudgetDetailFixture() - { - placer.div("vertical "); - placer.field("tabs") << budgetDetailPresenter.window(); - for(auto &&tab : budgetDetailPresenter.tabs()){ - placer.field("body").fasten(tab); - } - placer.collocate(); - } -}; - -SCENARIO_METHOD(BudgetDetailFixture, "BudgetDetailPresenter shows", "[budget-detail-presenter-class][presenter]") -{ - GIVEN("A BudgetDetailPresenter correcly initialized") - { - WHEN("Created") - { - THEN("Show 3 tabs") - { - UserInputChecker uic("", "the window should have three tabs, Summary, Estimates, Executions, the first one being selected by default"); - exec(host); - } - } - } -} - -SCENARIO_METHOD(BudgetDetailFixture, "BudgetDetailPresenter summary", "[budget-detail-presenter-class][presenter]") -{ - GIVEN("A BudgetDetailPresenter correcly initialized") - { - WHEN("Summary tab is selected") - { - THEN("Show the summary") - { - UserInputChecker uic("Click the first tab", "the summary is shown"); - exec(host); - REQUIRE(call_recorder.has("listEstimates")); - } - } - } -} - -SCENARIO_METHOD(BudgetDetailFixture, "BudgetDetailPresenter estimates", "[budget-detail-presenter-class][presenter]") -{ - GIVEN("A BudgetDetailPresenter correcly initialized") - { - WHEN("Estimates tab is selected") - { - THEN("Show the estimates") - { - UserInputChecker uic("Click the second tab", "the estimates are shown"); - exec(host); - } - } - } -} - -SCENARIO_METHOD(BudgetDetailFixture, "BudgetDetailPresenter executions", "[budget-detail-presenter-class][presenter]") -{ - GIVEN("A BudgetDetailPresenter correcly initialized") - { - WHEN("Execution tab is selected") - { - THEN("Show the executions") - { - UserInputChecker uic("Click the third tab", "the executions are shown"); - exec(host); - } - } - } -} diff --git a/presenter-test/BudgetSummaryPresenter-unit.cpp b/presenter-test/BudgetSummaryPresenter-unit.cpp new file mode 100644 index 0000000..26fdfb7 --- /dev/null +++ b/presenter-test/BudgetSummaryPresenter-unit.cpp @@ -0,0 +1,35 @@ +#include "common.hpp" +#include "stubs/BudgetControllerStub.hpp" +#include "BudgetSummaryPresenter.hpp" + +class BudgetSummaryFixture +{ + protected: + CallRecorder call_recorder; + nana::form host{API::make_center(800, 600)}; + nana::place placer { host }; + BudgetSummaryPresenter budgetDetailPresenter{host, make_unique(call_recorder)}; + + BudgetSummaryFixture() + { + placer.div("
"); + placer.field("main") << budgetDetailPresenter.window(); + placer.collocate(); + } +}; + +SCENARIO_METHOD(BudgetSummaryFixture, "BudgetDetailPresenter summary", "[budget-summary-presenter-class][presenter]") +{ + GIVEN("A BudgetSummaryPresenter correcly initialized") + { + WHEN("Summary tab is selected") + { + THEN("Show the summary") + { + UserInputChecker uic("", "the summary is shown"); + exec(host); + REQUIRE(call_recorder.has("listEstimates")); + } + } + } +} diff --git a/presenter-test/CMakeLists.txt b/presenter-test/CMakeLists.txt index ec1acec..6a46a1c 100644 --- a/presenter-test/CMakeLists.txt +++ b/presenter-test/CMakeLists.txt @@ -3,7 +3,7 @@ ####################### add_executable(presenter-test #Unit tests - BudgetDetailPresenter-unit + BudgetSummaryPresenter-unit EstimateDetailPresenter-unit EstimateListPresenter-unit ExecutionDetailPresenter-unit diff --git a/presenter-test/MainPresenter-unit.cpp b/presenter-test/MainPresenter-unit.cpp index 072f2a0..3fd9f73 100644 --- a/presenter-test/MainPresenter-unit.cpp +++ b/presenter-test/MainPresenter-unit.cpp @@ -55,6 +55,10 @@ SCENARIO("MainPresenter startup with no file", "[presenter][main-presenter-class } } } +} + +SCENARIO("MainPresenter startup with file", "[presenter][main-presenter-class][tabs]") +{ GIVEN("A Main Presenter with a filepath") { CallRecorder callRecorder; @@ -63,8 +67,9 @@ SCENARIO("MainPresenter startup with no file", "[presenter][main-presenter-class WHEN("Presented") { - cout << "If splasher opens, cancel. It is already wrong." << endl; - + UserInputChecker uic("", + "splasher does not open and the window should have three tabs, Summary, Estimates, " + "Executions, the first one being selected by default"); THEN("Does not show dialog at presentation") { bool calledListBudgets = false; @@ -95,7 +100,7 @@ struct CounterMainController : public MainController { }; // TODO: Fix the bug (Issue #42). -SCENARIO("MainPresenter startup with file", "[presenter][main-presenter-class][.][!mayfail]") +SCENARIO("MainPresenter startup with file2", "[presenter][main-presenter-class][.][!mayfail]") { GIVEN("A MainPresenter with a filepath") { @@ -245,3 +250,57 @@ SCENARIO("Exectution List Manipulation", "[presenter][main-presenter-class]") } } } + +SCENARIO("MainPresenter tab summary", "[main-presenter-class][presenter][tabs]") +{ + GIVEN("A MainPresenter with a file loaded") + { + CallRecorder callRecorder; + Manager manager = createManagerForTest(callRecorder); + MainPresenter mainPresenter{manager, "teste"}; + WHEN("Summary tab is selected") + { + THEN("Show the summary") + { + UserInputChecker uic("Click the first tab", "the summary is shown"); + exec(mainPresenter); + } + } + } +} + +SCENARIO("MainPresenter tab estimates", "[main-presenter-class][presenter][tabs]") +{ + GIVEN("A MainPresenter with a file loaded") + { + CallRecorder callRecorder; + Manager manager = createManagerForTest(callRecorder); + MainPresenter mainPresenter{manager, "teste"}; + WHEN("Estimates tab is selected") + { + THEN("Show the estimates") + { + UserInputChecker uic("Click the second tab", "the estimates are shown"); + exec(mainPresenter); + } + } + } +} + +SCENARIO("MainPresenter tab executions", "[main-presenter-class][presenter][tabs]") +{ + GIVEN("A MainPresenter with a file loaded") + { + CallRecorder callRecorder; + Manager manager = createManagerForTest(callRecorder); + MainPresenter mainPresenter{manager, "teste"}; + WHEN("Execution tab is selected") + { + THEN("Show the executions") + { + UserInputChecker uic("Click the third tab", "the executions are shown"); + exec(mainPresenter); + } + } + } +} diff --git a/presenter/BudgetDetailPresenter.hpp b/presenter/BudgetDetailPresenter.hpp deleted file mode 100644 index c7c3f42..0000000 --- a/presenter/BudgetDetailPresenter.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "BudgetController.hpp" -#include "BudgetView.hpp" -#include "EstimateListPresenter.hpp" -#include "ExecutionListPresenter.hpp" -#include "ControllerOwnerPresenter.hpp" - -namespace orca -{ -/** - * @class BudgetDetailPresenter - * @author Tales - * @date 14/02/2016 - * @file BudgetDetailPresenter.hpp - * @brief The tab control on main. - */ -class BudgetDetailPresenter : public ControllerOwnerPresenter -{ - using BASE = ControllerOwnerPresenter; - enum Tabs{ - SUMMARY, - ESTIMATE, - EXECUTION - }; - - public: - /** - * @brief Ctor - * @param wd - * @param controller - * @deprecated - */ - BudgetDetailPresenter(nana::window wd, std::unique_ptr controller); - /** - * @brief Ctor - * @param wd - * @param view - */ - BudgetDetailPresenter(nana::window wd, const BudgetView &view) : BudgetDetailPresenter(wd, view.controller()) {} - nana::window window() const { return t_main; } - std::vector tabs() const { return {l_summary, a_estimates.window(), a_executions.window()}; } - - void insertExecution(); - void editExecution(); - void deleteExecution(); - protected: - void activate(Tabs tab); - void refresh() override; - - private: - size_t a_currentControllerOwner = 0; - EstimateListPresenter a_estimates; - ExecutionListPresenter a_executions; - - nana::tabbar t_main; - nana::listbox l_summary; -}; -} diff --git a/presenter/BudgetDetailPresenter.cpp b/presenter/BudgetSummaryPresenter.cpp similarity index 51% rename from presenter/BudgetDetailPresenter.cpp rename to presenter/BudgetSummaryPresenter.cpp index 6783205..4d1fa22 100644 --- a/presenter/BudgetDetailPresenter.cpp +++ b/presenter/BudgetSummaryPresenter.cpp @@ -1,55 +1,13 @@ -#include "BudgetDetailPresenter.hpp" -#include "ExecutionDetailPresenter.hpp" +#include "BudgetSummaryPresenter.hpp" #include #include using namespace nana; using namespace std; -orca::BudgetDetailPresenter::BudgetDetailPresenter(nana::window wd, std::unique_ptr controller) - : BASE(move(controller)), a_estimates(wd, nullptr), a_executions(wd, nullptr), t_main(wd), l_summary(wd) +orca::BudgetSummaryPresenter::BudgetSummaryPresenter(nana::window wd, std::unique_ptr controller) + : BASE(move(controller)), l_summary(wd) { - t_main.append("Summary", l_summary, "summary"); - t_main.append("Estimates", a_estimates.window(), "estimates"); - t_main.append("Execution", a_executions.window(), "executions"); - t_main.activated(0); - - t_main.events().activated([this](auto&& arg) { - unique_ptr controller; - switch(a_currentControllerOwner) { - case 0: - controller = move(a_controller); - break; - case 1: - controller = a_estimates.devolve(); - break; - case 2: - controller = a_executions.devolve(); - break; - default: - throw logic_error("Invalid tab"); - } - a_currentControllerOwner = t_main.activated(); - switch(a_currentControllerOwner) { - case 0: - a_controller = move(controller); - this->refresh(); - break; - case 1: - a_estimates.receive(move(controller)); - break; - case 2: - a_executions.receive(move(controller)); - break; - default: - throw logic_error("Invalid tab"); - } - }); - a_executions.editViewHandler([this](auto&& view) { - ExecutionDetailPresenter edp(view); - edp.present(); - view = edp.get(); - }); l_summary.show_header(false); l_summary.append_header("Name"); l_summary.append_header("Value"); @@ -68,7 +26,7 @@ listbox::oresolver& operator<<(listbox::oresolver& ores, const SummaryItem& item return ores << item.name << item.value; } -void orca::BudgetDetailPresenter::refresh() +void orca::BudgetSummaryPresenter::refresh() { // Data enum ItensNumbers { @@ -115,22 +73,3 @@ void orca::BudgetDetailPresenter::refresh() catTotal.append(si); } } - -void orca::BudgetDetailPresenter::activate(Tabs tab) { t_main.activated(tab); } -void orca::BudgetDetailPresenter::insertExecution() -{ - activate(EXECUTION); - a_executions.insertExecution(); -} - -void orca::BudgetDetailPresenter::editExecution() -{ - activate(EXECUTION); - a_executions.editSelectedExecutions(); -} - -void orca::BudgetDetailPresenter::deleteExecution() -{ - activate(EXECUTION); - a_executions.deleteSelectedExecutions(); -} diff --git a/presenter/BudgetSummaryPresenter.hpp b/presenter/BudgetSummaryPresenter.hpp new file mode 100644 index 0000000..257497a --- /dev/null +++ b/presenter/BudgetSummaryPresenter.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include +#include "BudgetController.hpp" +#include "BudgetView.hpp" +#include "ControllerOwnerPresenter.hpp" + +namespace orca +{ +/** + * @class BudgetSummaryPresenter + * @author Tales + * @date 14/02/2016 + * @file BudgetDetailPresenter.hpp + * @brief Controls the summary + */ +class BudgetSummaryPresenter : public ControllerOwnerPresenter +{ + using BASE = ControllerOwnerPresenter; + + public: + /** + * @brief Ctor + * @param wd + * @param controller + * @deprecated + */ + BudgetSummaryPresenter(nana::window wd, std::unique_ptr controller); + /** + * @brief Ctor + * @param wd + * @param view + */ + BudgetSummaryPresenter(nana::window wd, const BudgetView &view) : BudgetSummaryPresenter(wd, view.controller()) {} + nana::window window() const { return l_summary; } + + protected: + void refresh() override; + + private: + nana::listbox l_summary; +}; +} diff --git a/presenter/CMakeLists.txt b/presenter/CMakeLists.txt index 309961d..20a6142 100644 --- a/presenter/CMakeLists.txt +++ b/presenter/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(presenter - BudgetDetailPresenter + BudgetSummaryPresenter EstimateDetailPresenter EstimateListPresenter ExecutionDetailPresenter diff --git a/presenter/MainPresenter.cpp b/presenter/MainPresenter.cpp index 863875b..b5b9752 100644 --- a/presenter/MainPresenter.cpp +++ b/presenter/MainPresenter.cpp @@ -1,10 +1,12 @@ -#include "MainController.hpp" +#include "MainPresenter.hpp" #include #include -#include "MainPresenter.hpp" +#include "BudgetController.hpp" +#include "MainController.hpp" #include "Manager.hpp" #include "SplasherPresenter.hpp" +#include "ExecutionDetailPresenter.hpp" using namespace nana; @@ -13,7 +15,10 @@ orca::MainPresenter::~MainPresenter() = default; orca::MainPresenter::MainPresenter(Manager &manager, const std::string &file_path) : a_manager(manager) , a_controller((file_path != "") ? a_manager.open(file_path) : nullptr) + , t_main(f_main) , a_budgetDetail(f_main, nullptr) + , a_estimates(f_main, nullptr) + , a_executions(f_main, nullptr) , f_main(API::make_center(800, 600)) , l_budgets(f_main) , mb_main(f_main) @@ -29,6 +34,35 @@ orca::MainPresenter::MainPresenter(Manager &manager, const std::string &file_pat } // Maybe put an else to devolve? }); + // Tabs + t_main.append("Summary", a_budgetDetail.window(), "summary"); + t_main.append("Estimates", a_estimates.window(), "estimates"); + t_main.append("Execution", a_executions.window(), "executions"); + t_main.activated(0); + + t_main.events().activated([this](auto &&arg) { + unique_ptr controller = this->popBudgetController(a_currentControllerOwner); + a_currentControllerOwner = static_cast(t_main.activated()); + switch(a_currentControllerOwner) { + case 0: + a_budgetDetail.receive(move(controller)); + break; + case 1: + a_estimates.receive(move(controller)); + break; + case 2: + a_executions.receive(move(controller)); + break; + default: + throw logic_error("Invalid tab"); + } + }); + a_executions.editViewHandler([this](auto &&view) { + ExecutionDetailPresenter edp(view); + edp.present(); + view = edp.get(); + }); + createMenu(); createLayout(); @@ -64,7 +98,7 @@ void orca::MainPresenter::createMenu() fileMenu.append("&Save", [this](auto &&) { a_controller->flush(); }); fileMenu.append_splitter(); fileMenu.append("E&xit", [this](auto &&) { f_main.close(); }); - + menu &budgetMenu = mb_main.push_back("&Budget"); budgetMenu.append("&New", [this](auto &&) { auto b = this->a_controller->pushBudget(); @@ -84,19 +118,13 @@ void orca::MainPresenter::createMenu() l_budgets.erase(last_item); } }); - + mb_main.push_back("E&stimate"); - + menu &executionMenu = mb_main.push_back("E&xecution"); - executionMenu.append("&New", [this](auto &&){ - a_budgetDetail.insertExecution(); - }); - executionMenu.append("&Edit Selected", [this](auto &&){ - a_budgetDetail.editExecution(); - }); - executionMenu.append("&Delete Selected", [this](auto &&){ - a_budgetDetail.deleteExecution(); - }); + executionMenu.append("&New", [this](auto &&) { this->insertExecution(); }); + executionMenu.append("&Edit Selected", [this](auto &&) { this->editExecution(); }); + executionMenu.append("&Delete Selected", [this](auto &&) { this->deleteExecution(); }); } void orca::MainPresenter::createLayout() @@ -106,10 +134,10 @@ void orca::MainPresenter::createLayout() placer.div(ss.str().c_str()); placer.field("menu") << mb_main; placer.field("budgets") << l_budgets; - placer.field("tabs") << a_budgetDetail.window(); - for(auto &&tab : a_budgetDetail.tabs()) { - placer.field("body").fasten(tab); - } + placer.field("tabs") << t_main; + placer.field("body").fasten(a_budgetDetail.window()); + placer.field("body").fasten(a_estimates.window()); + placer.field("body").fasten(a_executions.window()); placer.collocate(); if(a_controller) { @@ -153,4 +181,56 @@ void orca::MainPresenter::refreshBudgetList() a_budgetDetail.receive(a_controller->getBudget(last_item.text(0)).controller()); } -void orca::MainPresenter::close() { f_main.close(); } \ No newline at end of file +void orca::MainPresenter::close() { f_main.close(); } +void orca::MainPresenter::activate(Tab tab) { t_main.activated(tab); } +void orca::MainPresenter::insertExecution() +{ + activate(EXECUTION); + a_executions.insertExecution(); +} + +void orca::MainPresenter::editExecution() +{ + activate(EXECUTION); + a_executions.editSelectedExecutions(); +} + +void orca::MainPresenter::deleteExecution() +{ + activate(EXECUTION); + a_executions.deleteSelectedExecutions(); +} + +std::unique_ptr orca::MainPresenter::popBudgetController(Tab tab) +{ + switch(a_currentControllerOwner) { + case SUMMARY: + return a_budgetDetail.devolve(); + break; + case ESTIMATE: + return a_estimates.devolve(); + break; + case EXECUTION: + return a_executions.devolve(); + break; + default: + throw logic_error("Invalid tab"); + } +} + +void orca::MainPresenter::pushBudgetController(Tab tab, std::unique_ptr controller) +{ + switch(tab) { + case SUMMARY: + a_budgetDetail.receive(move(controller)); + break; + case ESTIMATE: + a_estimates.receive(move(controller)); + break; + case EXECUTION: + a_executions.receive(move(controller)); + break; + default: + throw logic_error("Invalid tab"); + } +} diff --git a/presenter/MainPresenter.hpp b/presenter/MainPresenter.hpp index 6edca13..c1f9e35 100644 --- a/presenter/MainPresenter.hpp +++ b/presenter/MainPresenter.hpp @@ -9,13 +9,17 @@ #include #include #include +#include -#include "BudgetDetailPresenter.hpp" +#include "BudgetSummaryPresenter.hpp" +#include "EstimateListPresenter.hpp" +#include "ExecutionListPresenter.hpp" #include "FormPresenter.hpp" namespace orca { // Forward Declaration +class BudgetController; class MainController; class Manager; @@ -30,6 +34,7 @@ class MainPresenter : public FormPresenter { using LoadErrorCallback = function; using LoadSuccessCallback = function; + enum Tab { SUMMARY, ESTIMATE, EXECUTION }; public: MainPresenter(Manager &manager, const std::string &file_path = ""); @@ -69,6 +74,14 @@ class MainPresenter : public FormPresenter void close(); + protected: + void activate(Tab tab); + std::unique_ptr popBudgetController(Tab tab); + void pushBudgetController(Tab tab, std::unique_ptrcontroller); + void insertExecution(); + void editExecution(); + void deleteExecution(); + private: void refreshBudgetList(); void createMenu(); @@ -78,11 +91,16 @@ class MainPresenter : public FormPresenter LoadSuccessCallback a_load_success_callback; Manager &a_manager; unique_ptr a_controller; + Tab a_currentControllerOwner = SUMMARY; // UI nana::form f_main; nana::listbox l_budgets; - BudgetDetailPresenter a_budgetDetail; + + nana::tabbar t_main; + BudgetSummaryPresenter a_budgetDetail; + EstimateListPresenter a_estimates; + ExecutionListPresenter a_executions; nana::menubar mb_main; nana::place placer; };