summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2024-07-16 17:31:57 +0200
committerFelix Morgner <felix.morgner@gmail.com>2024-07-16 20:10:59 +0200
commit474f1302eaf868e2b311d6561a69cae8f736a7c1 (patch)
tree175a359a653c9ed96835e41e055f5ac011c7ce33
parent2fd48d4ee446cb84f38605371eb9a05c70dde590 (diff)
downloadturns-474f1302eaf868e2b311d6561a69cae8f736a7c1.tar.xz
turns-474f1302eaf868e2b311d6561a69cae8f736a7c1.zip
app: move turn order management logic to turn_order
-rw-r--r--app/include/turns/app/widgets/turn_order_view.hpp11
-rw-r--r--app/src/widgets/participant_row.cpp1
-rw-r--r--app/src/widgets/turn_order_view.cpp44
-rw-r--r--app/src/windows/tracker.cpp20
-rw-r--r--domain/include/turns/domain/turn_order.hpp29
-rw-r--r--domain/src/turn_order.cpp63
-rw-r--r--domain/tests/turn_order.cpp88
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);
}
}