summaryrefslogtreecommitdiff
path: root/domain/src/turn_order.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'domain/src/turn_order.cpp')
-rw-r--r--domain/src/turn_order.cpp237
1 files changed, 123 insertions, 114 deletions
diff --git a/domain/src/turn_order.cpp b/domain/src/turn_order.cpp
index 61ccdca..0f8b6e8 100644
--- a/domain/src/turn_order.cpp
+++ b/domain/src/turn_order.cpp
@@ -2,11 +2,11 @@
#include "turns/domain/participant.hpp"
+#include <algorithm>
#include <compare>
#include <limits>
#include <typeinfo>
-#include <glibmm/binding.h>
#include <glibmm/refptr.h>
namespace turns::domain
@@ -32,194 +32,203 @@ namespace turns::domain
};
} // namespace
+ /** Construction */
+
+ turn_order::turn_order()
+ : Glib::ObjectBase{typeid(turn_order)}
+ , Gio::ListModel{}
+ {
+ }
+
auto turn_order::create() -> Glib::RefPtr<turn_order>
{
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_active_participant(*this, "active_participant", invalid_participant_index)
- , m_empty{*this, "empty", true}
- , m_has_next{*this, "has-next", false}
- , m_has_previous{*this, "has-previous", false}
- , m_running{*this, "running", false}
- , m_round{*this, "round", 0}
+ /** Queries */
+
+ auto turn_order::is_empty() const -> Glib::PropertyProxy_ReadOnly<is_empty_type>
+ {
+ return m_is_empty.get_proxy();
+ }
+
+ auto turn_order::has_next() const -> Glib::PropertyProxy_ReadOnly<has_next_type>
+ {
+ return m_has_next.get_proxy();
+ }
+
+ auto turn_order::has_previous() const -> Glib::PropertyProxy_ReadOnly<has_previous_type>
+ {
+ return m_has_previous.get_proxy();
+ }
+
+ auto turn_order::is_running() const -> Glib::PropertyProxy_ReadOnly<is_running_type>
{
- Glib::Binding::bind_property(m_model->property_n_items(), m_empty.get_proxy(), Glib::Binding::Flags::DEFAULT, [](auto n) {
- return n == 0;
- });
+ return m_is_running.get_proxy();
+ }
+
+ auto turn_order::round_number() const -> Glib::PropertyProxy_ReadOnly<round_number_type>
+ {
+ return m_round_number.get_proxy();
}
/** Modifiers */
auto turn_order::add(Glib::ustring const & name, float priority, disposition disposition) -> void
{
- auto participant = participant::create(name, priority, disposition);
- if (auto [found, index] = m_model->find(participant, equal_comparator); !found)
- {
- auto position = m_model->insert_sorted(participant, comparator);
- participant->property_priority().signal_changed().connect([this] { m_model->sort(comparator); });
+ auto entry = participant::create(name, priority, disposition);
+ entry->priority().signal_changed().connect(sigc::bind(sigc::mem_fun(*this, &turn_order::handle_priority_changed), entry));
+ auto position = std::distance(m_data.cbegin(), insert(entry));
+ items_changed(position, 0, 1);
- if (m_active_participant != invalid_participant_index && position <= m_active_participant)
- {
- m_active_participant = m_active_participant + 1;
- }
+ if (get_n_items() == 1)
+ {
+ m_is_empty = false;
+ m_has_next = true;
}
}
auto turn_order::clear() -> void
{
- m_model->remove_all();
- m_active_participant = invalid_participant_index;
+ m_is_running = false;
+ m_is_empty = true;
m_has_next = false;
m_has_previous = false;
- m_running = false;
+ m_active.reset();
+ m_round_number = invalid_round_number;
+
+ auto old_size = get_n_items();
+ m_data.clear();
+ items_changed(0, old_size, 0);
}
auto turn_order::next() -> void
{
- m_active_participant = (m_active_participant + 1) % size();
- if (!m_active_participant)
+ auto old_active = *m_active;
+ m_active = m_active.transform([this](auto index) { return (index + 1) % get_n_items(); });
+
+ m_has_previous = true;
+ m_data[old_active]->is_active() = false;
+ m_data[*m_active]->is_active() = true;
+
+ if (m_active == 0)
{
- m_round = round() + 1;
+ m_round_number = m_round_number + 1;
}
- m_has_previous = m_active_participant || m_round;
}
auto turn_order::previous() -> void
{
- if (!m_has_previous)
+ if (!(m_has_previous && m_is_running))
{
return;
}
- if (m_active_participant)
- {
- m_active_participant = m_active_participant - 1;
- }
- else if (m_round)
+ auto old_active = *m_active;
+ m_active = m_active.transform([this](auto index) { return index ? index - 1 : get_n_items() - 1; });
+
+ m_has_previous = m_round_number > 0 || m_active > 0;
+ m_data[old_active]->is_active() = false;
+ m_data[*m_active]->is_active() = true;
+
+ if (m_active == 0)
{
- m_round = round() - 1;
- m_active_participant = size() - 1;
+ m_round_number = m_round_number - 1;
}
-
- m_has_previous = m_active_participant || m_round;
}
- auto turn_order::remove(unsigned int index) -> void
+ auto turn_order::remove(unsigned index) -> void
{
- m_model->remove(index);
- if (empty())
+ if (index >= get_n_items())
{
- m_active_participant = invalid_participant_index;
- m_has_next = false;
- m_has_previous = false;
- m_running = false;
+ return;
}
- else if (m_active_participant != invalid_participant_index)
+
+ auto position = m_data.begin() + index;
+ m_data.erase(position);
+ items_changed(index, 1, 0);
+ if (get_n_items() == 0)
{
- if (m_active_participant > size() - 1)
- {
- m_active_participant = size() - 1;
- }
- else if (index <= m_active_participant)
- {
- m_active_participant = m_active_participant - 1;
- }
+ m_is_empty = true;
+ m_is_running = false;
+ m_has_next = false;
}
}
- auto turn_order::reset() -> void
- {
- m_running = false;
- m_active_participant = 0;
- }
-
auto turn_order::start() -> void
{
- if (m_active_participant == invalid_participant_index)
+ if (!m_active)
{
- m_active_participant = 0;
+ m_active = 0;
+ m_data[*m_active]->is_active() = true;
}
- m_running = true;
- m_has_next = true;
+ if (m_round_number == invalid_round_number)
+ {
+ m_round_number = 0;
+ }
+ m_is_running = true;
}
auto turn_order::stop() -> void
{
- m_running = false;
- m_has_next = false;
- }
-
- /** Querries */
-
- auto turn_order::active_participant() const noexcept -> active_participant_type
- {
- return m_active_participant;
- }
-
- auto turn_order::empty() const noexcept -> bool
- {
- return m_empty;
- }
-
- auto turn_order::get(unsigned int index) const noexcept -> Glib::RefPtr<participant>
- {
- return m_model->get_item(index);
+ m_is_running = false;
}
- auto turn_order::list_model() -> Glib::RefPtr<Gio::ListModel>
- {
- return m_model;
- }
+ /** ListModel implementation */
- auto turn_order::round() const noexcept -> round_type
+ auto turn_order::get_item_type_vfunc() -> GType
{
- return m_round;
+ return participant::get_type();
}
- auto turn_order::running() const noexcept -> running_type
+ auto turn_order::get_n_items_vfunc() -> unsigned
{
- return m_running;
+ return m_data.size();
}
- auto turn_order::size() const noexcept -> unsigned int
+ auto turn_order::get_item_vfunc(unsigned position) -> void *
{
- return m_model->get_n_items();
+ if (position >= get_n_items())
+ {
+ return nullptr;
+ }
+ auto item = m_data[position];
+ item->reference();
+ return item->gobj();
}
- /** Properties */
+ /** Signal handlers */
- auto turn_order::property_active_participant() const -> Glib::PropertyProxy_ReadOnly<active_participant_type>
+ auto turn_order::handle_priority_changed(value_type entry) -> void
{
- return m_active_participant.get_proxy();
- }
-
- auto turn_order::property_empty() const -> Glib::PropertyProxy_ReadOnly<bool>
- {
- return m_empty.get_proxy();
- }
+ auto original_position = find(entry);
+ auto original_index = distance(m_data.cbegin(), original_position);
+ auto target_position = std::ranges::upper_bound(m_data, entry, comparator);
+ if (original_position == target_position)
+ {
+ return;
+ }
- auto turn_order::property_has_next() const -> Glib::PropertyProxy_ReadOnly<has_next_type>
- {
- return m_has_next.get_proxy();
+ m_data.erase(original_position);
+ auto inserted_position = insert(entry);
+ items_changed(0, get_n_items(), get_n_items());
+ if (m_active == original_index)
+ {
+ m_active = distance(m_data.cbegin(), inserted_position);
+ m_has_previous = m_round_number > 0 || m_active > 0;
+ }
}
- auto turn_order::property_has_previous() const -> Glib::PropertyProxy_ReadOnly<has_previous_type>
- {
- return m_has_previous.get_proxy();
- }
+ /** Data management */
- auto turn_order::property_running() const -> Glib::PropertyProxy_ReadOnly<running_type>
+ auto turn_order::find(value_type entry) const -> const_iterator
{
- return m_running.get_proxy();
+ return std::ranges::find(m_data, entry);
}
- auto turn_order::property_round() const -> Glib::PropertyProxy_ReadOnly<round_type>
+ auto turn_order::insert(value_type entry) -> const_iterator
{
- return m_round.get_proxy();
+ return m_data.insert(std::ranges::upper_bound(m_data, entry, comparator), entry);
}
} // namespace turns::domain \ No newline at end of file