diff options
| -rw-r--r-- | app/include/turns/app/widgets/turn_order_view.hpp | 11 | ||||
| -rw-r--r-- | app/src/widgets/participant_row.cpp | 1 | ||||
| -rw-r--r-- | app/src/widgets/turn_order_view.cpp | 44 | ||||
| -rw-r--r-- | app/src/windows/tracker.cpp | 20 | ||||
| -rw-r--r-- | domain/include/turns/domain/turn_order.hpp | 29 | ||||
| -rw-r--r-- | domain/src/turn_order.cpp | 63 | ||||
| -rw-r--r-- | domain/tests/turn_order.cpp | 88 |
7 files changed, 135 insertions, 121 deletions
diff --git a/app/include/turns/app/widgets/turn_order_view.hpp b/app/include/turns/app/widgets/turn_order_view.hpp index 07d1712..0122f4a 100644 --- a/app/include/turns/app/widgets/turn_order_view.hpp +++ b/app/include/turns/app/widgets/turn_order_view.hpp @@ -26,22 +26,13 @@ namespace turns::app::widgets turn_order_view(); - auto append(Glib::ustring name, float priority, domain::disposition disposition) -> void; - auto clear() -> void; - auto get(std::size_t index) -> Glib::RefPtr<domain::participant>; - auto start() -> void; - auto remove(std::size_t index) -> void; - - auto get_is_empty() const noexcept -> bool; - auto property_is_empty() const -> Glib::PropertyProxy_ReadOnly<bool>; + auto get_model() const noexcept -> Glib::RefPtr<domain::turn_order>; private: auto handle_create_row(Glib::RefPtr<Glib::Object> const item) -> Gtk::Widget *; Glib::RefPtr<domain::turn_order> m_model; Gtk::ListBox * m_view; - - Glib::Property<bool> m_is_empty; }; } // namespace turns::app::widgets diff --git a/app/src/widgets/participant_row.cpp b/app/src/widgets/participant_row.cpp index 269aa15..54ad20e 100644 --- a/app/src/widgets/participant_row.cpp +++ b/app/src/widgets/participant_row.cpp @@ -9,6 +9,7 @@ #include <glibmm/i18n.h> #include <glibmm/ustring.h> #include <glibmm/variant.h> +#include <gtkmm/stringlist.h> namespace turns::app::widgets { diff --git a/app/src/widgets/turn_order_view.cpp b/app/src/widgets/turn_order_view.cpp index d5520ca..700dfd3 100644 --- a/app/src/widgets/turn_order_view.cpp +++ b/app/src/widgets/turn_order_view.cpp @@ -21,51 +21,13 @@ namespace turns::app::widgets , template_widget<turn_order_view, Gtk::ScrolledWindow>{TEMPLATE} , m_model{domain::turn_order::create()} , m_view{get_widget<Gtk::ListBox>("view")} - , m_is_empty{*this, "is_empty", true} { - m_view->bind_model(m_model, sigc::mem_fun(*this, &turn_order_view::handle_create_row)); - - // clang-format off - Glib::Binding::bind_property(m_model->property_n_items(), - m_is_empty.get_proxy(), - Glib::Binding::Flags::DEFAULT, - [](auto n) { return n == 0; }); - // clang-format on - } - - auto turn_order_view::append(Glib::ustring name, float priority, domain::disposition disposition) -> void - { - auto participant = domain::participant::create(name, priority, disposition); - m_model->append(participant); - } - - auto turn_order_view::clear() -> void - { - m_model->remove_all(); - } - - auto turn_order_view::get(std::size_t index) -> Glib::RefPtr<domain::participant> - { - return m_model->get_item(index); - } - - auto turn_order_view::start() -> void - { - } - - auto turn_order_view::remove(std::size_t index) -> void - { - m_model->remove(index); - } - - auto turn_order_view::get_is_empty() const noexcept -> bool - { - return m_is_empty; + m_view->bind_model(m_model->list_model(), sigc::mem_fun(*this, &turn_order_view::handle_create_row)); } - auto turn_order_view::property_is_empty() const -> Glib::PropertyProxy_ReadOnly<bool> + auto turn_order_view::get_model() const noexcept -> Glib::RefPtr<domain::turn_order> { - return m_is_empty.get_proxy(); + return m_model; } auto turn_order_view::handle_create_row(Glib::RefPtr<Glib::Object> const item) -> Gtk::Widget * diff --git a/app/src/windows/tracker.cpp b/app/src/windows/tracker.cpp index 3c39a2f..639cf8a 100644 --- a/app/src/windows/tracker.cpp +++ b/app/src/windows/tracker.cpp @@ -36,31 +36,31 @@ namespace turns::app::windows { m_stack->add(*m_turn_order); - auto clear_action = add_action("clear", sigc::mem_fun(*m_turn_order, &widgets::turn_order_view::clear)); + auto clear_action = add_action("clear", sigc::mem_fun(*m_turn_order->get_model(), &domain::turn_order::remove_all)); add_action("add_participant", sigc::mem_fun(*this, &tracker::handle_add_participant)); add_action_with_parameter("delete", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::handle_delete_participant)); add_action_with_parameter("edit", Glib::VARIANT_TYPE_INT32, sigc::mem_fun(*this, &tracker::handle_edit_participant)); - auto start_action = add_action("start", sigc::mem_fun(*m_turn_order, &widgets::turn_order_view::start)); + auto start_action = add_action("start", sigc::mem_fun(*m_turn_order->get_model(), &domain::turn_order::start)); - Glib::Binding::bind_property(m_turn_order->property_is_empty(), + Glib::Binding::bind_property(m_turn_order->get_model()->property_empty(), clear_action->property_enabled(), Glib::Binding::Flags::SYNC_CREATE | Glib::Binding::Flags::INVERT_BOOLEAN); - Glib::Binding::bind_property(m_turn_order->property_is_empty(), + Glib::Binding::bind_property(m_turn_order->get_model()->property_empty(), m_controls->property_reveal_child(), Glib::Binding::Flags::SYNC_CREATE | Glib::Binding::Flags::INVERT_BOOLEAN); - Glib::Binding::bind_property(m_turn_order->property_is_empty(), + Glib::Binding::bind_property(m_turn_order->get_model()->property_empty(), m_stack->property_visible_child(), Glib::Binding::Flags::SYNC_CREATE, [this](auto empty) { return empty ? m_empty : m_turn_order; }); - Glib::Binding::bind_property(m_turn_order->property_is_empty(), + Glib::Binding::bind_property(m_turn_order->get_model()->property_empty(), start_action->property_enabled(), Glib::Binding::Flags::SYNC_CREATE | Glib::Binding::Flags::INVERT_BOOLEAN); // clang-format off - Glib::Binding::bind_property(m_turn_order->property_is_empty(), + Glib::Binding::bind_property(m_turn_order->get_model()->property_empty(), m_subtitle, Glib::Binding::Flags::SYNC_CREATE, [](auto empty) { @@ -73,20 +73,20 @@ namespace turns::app::windows { auto [lifeline, dialog] = editor_for(nullptr); dialog->present(this); - dialog->signal_finished().connect(sigc::mem_fun(*m_turn_order, &widgets::turn_order_view::append)); + dialog->signal_finished().connect([this](auto n, auto p, auto d) { m_turn_order->get_model()->append(n, p, d); }); } auto tracker::handle_delete_participant(Glib::VariantBase param) -> void { auto index = Glib::VariantBase::cast_dynamic<Glib::Variant<int>>(param); - m_turn_order->remove(index.get()); + m_turn_order->get_model()->remove(index.get()); } auto tracker::handle_edit_participant(Glib::VariantBase param) -> void { static_cast<void>(param); auto index = Glib::VariantBase::cast_dynamic<Glib::Variant<int>>(param); - auto participant = m_turn_order->get(index.get()); + auto participant = m_turn_order->get_model()->get_participant(index.get()); auto [lifeline, dialog] = editor_for(participant); dialog->present(this); } diff --git a/domain/include/turns/domain/turn_order.hpp b/domain/include/turns/domain/turn_order.hpp index d7f8821..8f65104 100644 --- a/domain/include/turns/domain/turn_order.hpp +++ b/domain/include/turns/domain/turn_order.hpp @@ -5,29 +5,40 @@ #include "turns/domain/participant.hpp" #include <giomm/liststore.h> +#include <glibmm/property.h> #include <glibmm/refptr.h> #include <glibmm/ustring.h> namespace turns::domain { - struct turn_order : Gio::ListStore<participant> + struct turn_order : Glib::Object { - using super = Gio::ListStore<participant>; - using super::super; - - using super::remove; - auto static create() -> Glib::RefPtr<turn_order>; + turn_order(); + auto append(Glib::RefPtr<participant> item) -> void; auto append(Glib::ustring const & name, float priority, disposition disposition) -> void; + + auto get_participant(unsigned int index) -> Glib::RefPtr<participant>; + + auto list_model() -> Glib::RefPtr<Gio::ListModel>; + + auto n_participants() -> unsigned int; + auto remove(Glib::RefPtr<participant> item) -> void; + auto remove(unsigned int index) -> void; + auto remove_all() -> void; + + auto start() -> void; + + auto get_empty() const noexcept -> bool; + auto property_empty() const -> Glib::PropertyProxy_ReadOnly<bool>; private: - using super::insert; - using super::insert_sorted; - using super::sort; + Glib::RefPtr<Gio::ListStore<participant>> m_model; + Glib::Property<bool> m_empty; }; } // namespace turns::domain diff --git a/domain/src/turn_order.cpp b/domain/src/turn_order.cpp index 7216239..6435db9 100644 --- a/domain/src/turn_order.cpp +++ b/domain/src/turn_order.cpp @@ -3,7 +3,9 @@ #include "turns/domain/participant.hpp" #include <compare> +#include <typeinfo> +#include <glibmm/binding.h> #include <glibmm/refptr.h> namespace turns::domain @@ -34,14 +36,22 @@ namespace turns::domain return Glib::make_refptr_for_instance(new turn_order{}); } + turn_order::turn_order() + : Glib::ObjectBase{typeid(turn_order)} + , m_model{Gio::ListStore<participant>::create()} + , m_empty{*this, "empty", true} + { + Glib::Binding::bind_property(m_model->property_n_items(), m_empty.get_proxy(), Glib::Binding::Flags::DEFAULT, [](auto n) { + return n == 0; + }); + } + auto turn_order::append(Glib::RefPtr<participant> item) -> void { - if (auto [found, index] = find(item, equal_comparator); !found) + if (auto [found, index] = m_model->find(item, equal_comparator); !found) { - insert_sorted(item, comparator); - item->property_priority().signal_changed().connect([this] { - sort(comparator); - }); + m_model->insert_sorted(item, comparator); + item->property_priority().signal_changed().connect([this] { m_model->sort(comparator); }); } } @@ -51,12 +61,51 @@ namespace turns::domain append(participant); } + auto turn_order::get_participant(unsigned int index) -> Glib::RefPtr<participant> + { + return m_model->get_item(index); + } + + auto turn_order::list_model() -> Glib::RefPtr<Gio::ListModel> + { + return m_model; + } + + auto turn_order::n_participants() -> unsigned int + { + return m_model->get_n_items(); + } + auto turn_order::remove(Glib::RefPtr<participant> item) -> void { - if (auto [was_found, index] = find(item); was_found) + if (auto [was_found, index] = m_model->find(item); was_found) { - super::remove(index); + remove(index); } } + auto turn_order::remove(unsigned int index) -> void + { + m_model->remove(index); + } + + auto turn_order::remove_all() -> void + { + m_model->remove_all(); + } + + auto turn_order::start() -> void + { + } + + auto turn_order::get_empty() const noexcept -> bool + { + return m_empty; + } + + auto turn_order::property_empty() const -> Glib::PropertyProxy_ReadOnly<bool> + { + return m_empty.get_proxy(); + } + } // namespace turns::domain
\ No newline at end of file diff --git a/domain/tests/turn_order.cpp b/domain/tests/turn_order.cpp index f1f2653..9feb47a 100644 --- a/domain/tests/turn_order.cpp +++ b/domain/tests/turn_order.cpp @@ -13,79 +13,79 @@ namespace turns::domain::tests TEST_CASE("A freshly constructed turn order") { - auto instance = turn_order{}; + auto instance = turn_order::create(); SECTION("can be created") { - REQUIRE(turn_order::create()); + REQUIRE(instance); } SECTION("has 0 items") { - REQUIRE(instance.get_n_items() == 0); + REQUIRE(instance->n_participants() == 0); } SECTION("accepts a new participant in form of a refptr") { - instance.append(participant::create("Honey Bunches of Oats", 12, disposition::friendly)); - REQUIRE(instance.get_n_items() == 1); + instance->append(participant::create("Honey Bunches of Oats", 12, disposition::friendly)); + REQUIRE(instance->n_participants() == 1); } SECTION("accepts a new participant in form of components") { - instance.append("River along the Field", 14, disposition::friendly); - REQUIRE(instance.get_n_items() == 1); + instance->append("River along the Field", 14, disposition::friendly); + REQUIRE(instance->n_participants() == 1); } SECTION("does nothing when trying to remove an item by refptr if no items were added beforehand") { - instance.remove(participant::create("Patch in the Forest", 3, disposition::friendly)); - REQUIRE(instance.get_n_items() == 0); + instance->remove(participant::create("Patch in the Forest", 3, disposition::friendly)); + REQUIRE(instance->n_participants() == 0); } SECTION("does nothing when trying to remove an item by index if no items were added beforehand") { - instance.remove(5); - REQUIRE(instance.get_n_items() == 0); + instance->remove(5); + REQUIRE(instance->n_participants() == 0); } SECTION("allows the removal of an item by refptr if the same item was added beforehand") { auto item = participant::create("Blank Canvas", 23, disposition::friendly); - instance.append(item); - instance.remove(item); - REQUIRE(instance.get_n_items() == 0); + instance->append(item); + instance->remove(item); + REQUIRE(instance->n_participants() == 0); } SECTION("does nothing when trying to remove an item by refptr that was not added beforehand") { auto item = participant::create("Blank Canvas", 23, disposition::friendly); - instance.append(item); - instance.remove(participant::create("Spell of Rain", 6, disposition::friendly)); - REQUIRE(instance.get_n_items() == 1); + instance->append(item); + instance->remove(participant::create("Spell of Rain", 6, disposition::friendly)); + REQUIRE(instance->n_participants() == 1); } SECTION("automatically sorts appended refptrs in descending order of priority") { SECTION("when appending the higher one last") { - instance.append(participant::create("Snow on the Field", 2, disposition::friendly)); - instance.append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); - REQUIRE(instance.get_item(0)->get_name() == "Bees behind the Cottage"); + instance->append(participant::create("Snow on the Field", 2, disposition::friendly)); + instance->append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); + REQUIRE(instance->get_participant(0)->get_name() == "Bees behind the Cottage"); } SECTION("when appending the higher one first") { - instance.append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); - instance.append(participant::create("Snow on the Field", 2, disposition::friendly)); - REQUIRE(instance.get_item(0)->get_name() == "Bees behind the Cottage"); + instance->append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); + instance->append(participant::create("Snow on the Field", 2, disposition::friendly)); + REQUIRE(instance->get_participant(0)->get_name() == "Bees behind the Cottage"); } SECTION("keeping the insertion order when appending items with equal priority") { - instance.append(participant::create("Snow on the Field", 8, disposition::friendly)); - instance.append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); - REQUIRE(instance.get_item(0)->get_name() == "Snow on the Field"); + instance->append(participant::create("Snow on the Field", 8, disposition::friendly)); + instance->append(participant::create("Bees behind the Cottage", 8, disposition::friendly)); + REQUIRE(instance->get_participant(0)->get_name() == "Snow on the Field"); } } @@ -93,48 +93,48 @@ namespace turns::domain::tests { SECTION("when appending the higher one last") { - instance.append("Tree Blossom", 6, disposition::friendly); - instance.append("Fish in the River", 12, disposition::friendly); - REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + instance->append("Tree Blossom", 6, disposition::friendly); + instance->append("Fish in the River", 12, disposition::friendly); + REQUIRE(instance->get_participant(0)->get_name() == "Fish in the River"); } SECTION("when appending the higher one first") { - instance.append("Fish in the River", 12, disposition::friendly); - instance.append("Tree Blossom", 6, disposition::friendly); - REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + instance->append("Fish in the River", 12, disposition::friendly); + instance->append("Tree Blossom", 6, disposition::friendly); + REQUIRE(instance->get_participant(0)->get_name() == "Fish in the River"); } SECTION("keeping the insertion order when appending items with equal priority") { - instance.append("Fish in the River", 6, disposition::friendly); - instance.append("Tree Blossom", 6, disposition::friendly); - REQUIRE(instance.get_item(0)->get_name() == "Fish in the River"); + instance->append("Fish in the River", 6, disposition::friendly); + instance->append("Tree Blossom", 6, disposition::friendly); + REQUIRE(instance->get_participant(0)->get_name() == "Fish in the River"); } } SECTION("does not accept the same item twice by the same refptr") { auto item = participant::create("Angelic Berry", 9, disposition::friendly); - instance.append(item); - instance.append(item); - REQUIRE(instance.get_n_items() == 1); + instance->append(item); + instance->append(item); + REQUIRE(instance->n_participants() == 1); } SECTION("does not accept the same item twice by different refptrs") { auto item_one = participant::create("Misty Meadow", 14.2, disposition::friendly); auto item_two = participant::create("Misty Meadow", 14.2, disposition::friendly); - instance.append(item_one); - instance.append(item_two); - REQUIRE(instance.get_n_items() == 1); + instance->append(item_one); + instance->append(item_two); + REQUIRE(instance->n_participants() == 1); } SECTION("does not accept the same item twice by components") { - instance.append("Frozen Apple Tree", 2.1, disposition::friendly); - instance.append("Frozen Apple Tree", 2.1, disposition::friendly); - REQUIRE(instance.get_n_items() == 1); + instance->append("Frozen Apple Tree", 2.1, disposition::friendly); + instance->append("Frozen Apple Tree", 2.1, disposition::friendly); + REQUIRE(instance->n_participants() == 1); } } |
