diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2024-07-23 15:08:19 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2024-07-23 15:08:19 +0200 |
| commit | 4ec6a2ae12b6adb843c0777649ff45a741ca6cbc (patch) | |
| tree | 93dc2ba99dbcb42b2af73f0a3c4cd4f0c0f091c4 /domain/src/turn_order.cpp | |
| parent | 5f4249a37ce816b8deceb299bc841190fbb15983 (diff) | |
| download | turns-4ec6a2ae12b6adb843c0777649ff45a741ca6cbc.tar.xz turns-4ec6a2ae12b6adb843c0777649ff45a741ca6cbc.zip | |
domain: redesign turn_order
Diffstat (limited to 'domain/src/turn_order.cpp')
| -rw-r--r-- | domain/src/turn_order.cpp | 237 |
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 |
