diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2025-05-19 13:42:39 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2025-05-19 13:42:39 +0200 |
| commit | 0a5f3b25214c11556f62ce04601c06812a3464d8 (patch) | |
| tree | d35ed88fc142927f6d34af7e0ddcc4bafb25145a /lib/src | |
| parent | d0b647c3156b07c70e9831aa86ef76ee40413d0c (diff) | |
| download | turns-0a5f3b25214c11556f62ce04601c06812a3464d8.tar.xz turns-0a5f3b25214c11556f62ce04601c06812a3464d8.zip | |
lib: add support for different sort modes
Diffstat (limited to 'lib/src')
| -rw-r--r-- | lib/src/turns-turn-order.cpp | 191 | ||||
| -rw-r--r-- | lib/src/turns-turn-order.h | 9 | ||||
| -rw-r--r-- | lib/src/turnsmm/enums.cpp | 5 | ||||
| -rw-r--r-- | lib/src/turnsmm/enums.hpp | 7 | ||||
| -rw-r--r-- | lib/src/turnsmm/turn-order.cpp | 21 | ||||
| -rw-r--r-- | lib/src/turnsmm/turn-order.hpp | 6 |
6 files changed, 194 insertions, 45 deletions
diff --git a/lib/src/turns-turn-order.cpp b/lib/src/turns-turn-order.cpp index b7bd03e..496ef2d 100644 --- a/lib/src/turns-turn-order.cpp +++ b/lib/src/turns-turn-order.cpp @@ -1,10 +1,12 @@ #include "turns-turn-order.h" +#include "turns-enums.h" #include "turns-participant.h" #include <gio/gio.h> #include <glib-object.h> #include <glib.h> +#include <glibconfig.h> #include <array> #include <bit> @@ -18,9 +20,10 @@ struct _TurnsTurnOrder GSList * participants; gboolean running; + TurnsTurnOrderSortMode sort_mode; }; -static void turns_turn_order_list_model_init(GListModelInterface * iface); +auto static turns_turn_order_list_model_init(GListModelInterface * iface) -> void; G_DEFINE_FINAL_TYPE_WITH_CODE(TurnsTurnOrder, turns_turn_order, @@ -34,67 +37,123 @@ namespace enum struct property { Running = 1, + SortMode, N_PROPERTIES, }; auto static constinit properties = std::array<GParamSpec *, static_cast<std::size_t>(property::N_PROPERTIES)>{}; - auto compare_participant(TurnsParticipant const * lhs, TurnsParticipant const * rhs) + /* Private Functions */ + + auto static inline compare_participant(TurnsParticipant const * lhs, TurnsParticipant const * rhs, TurnsTurnOrderSortMode sort_mode) { auto left_priority = turns_participant_get_priority(lhs); auto right_priority = turns_participant_get_priority(rhs); - if (left_priority < right_priority) - { - return 1; - } - else if (left_priority > right_priority) - { - return -1; - } - else + auto ascending_result = [&] { + if (left_priority < right_priority) + { + return -1; + } + else if (left_priority > right_priority) + { + return 1; + } + else + { + return 0; + } + }(); + + if (sort_mode == TURNS_TURN_ORDER_SORT_MODE_DESCENDING) { - return 0; + return ascending_result * -1; } + + return ascending_result; } - auto finalize(GObject * self) + auto static inline sort_participants(TurnsTurnOrder * self) { - auto instance = TURNS_TURN_ORDER(self); + auto const sort_mode = turns_turn_order_get_sort_mode(self); + auto const sort_data = std::bit_cast<void *>(static_cast<guintptr>(sort_mode)); + auto const sort_function = std::bit_cast<GCompareDataFunc>(&compare_participant); - g_slist_free_full(instance->participants, g_object_unref); - - G_OBJECT_CLASS(turns_turn_order_parent_class)->finalize(self); - } + self->participants = g_slist_sort_with_data(self->participants, sort_function, sort_data); - auto get_property(GObject * self, guint id, GValue * value, GParamSpec * specification) -> void - { - auto instance = TURNS_TURN_ORDER(self); + auto const participant_count = turns_turn_order_get_participant_count(self); - switch (static_cast<property>(id)) - { - case property::Running: - return g_value_set_boolean(value, turns_turn_order_get_running(instance)); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification); - } + g_list_model_items_changed(G_LIST_MODEL(self), 0, participant_count, participant_count); } + /* Signal Handlers */ + auto handle_participant_property_changed(TurnsParticipant const *, GParamSpec *, TurnsTurnOrder * self) { - self->participants = g_slist_sort(self->participants, std::bit_cast<GCompareFunc>(&compare_participant)); + sort_participants(self); } } // namespace G_BEGIN_DECLS +/* GObject Construction / Destruction */ + +auto static turns_turn_order_init(TurnsTurnOrder * self) -> void +{ + self->participants = nullptr; + self->running = false; + self->sort_mode = TURNS_TURN_ORDER_SORT_MODE_DESCENDING; +} + +auto static turns_turn_order_finalize(GObject * self) -> void +{ + auto instance = TURNS_TURN_ORDER(self); + + g_slist_free_full(instance->participants, g_object_unref); + + G_OBJECT_CLASS(turns_turn_order_parent_class)->finalize(self); +} + +/* GObject Property Accessors */ + +auto static turns_turn_order_get_property(GObject * self, guint id, GValue * value, GParamSpec * specification) -> void +{ + auto instance = TURNS_TURN_ORDER(self); + + switch (static_cast<property>(id)) + { + case property::Running: + return g_value_set_boolean(value, turns_turn_order_get_running(instance)); + case property::SortMode: + return g_value_set_enum(value, turns_turn_order_get_sort_mode(instance)); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification); + } +} + +auto static turns_turn_order_set_property(GObject * self, guint id, GValue const * value, GParamSpec * specification) -> void +{ + auto instance = TURNS_TURN_ORDER(self); + + switch (static_cast<property>(id)) + { + case property::SortMode: + return turns_turn_order_set_sort_mode(instance, static_cast<TurnsTurnOrderSortMode>(g_value_get_enum(value))); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification); + } +} + +/* GType Class Initialization */ + static void turns_turn_order_class_init(TurnsTurnOrderClass * klass) { auto object_class = G_OBJECT_CLASS(klass); - object_class->finalize = finalize; - object_class->get_property = get_property; + object_class->finalize = turns_turn_order_finalize; + object_class->get_property = turns_turn_order_get_property; + object_class->set_property = turns_turn_order_set_property; properties[static_cast<std::size_t>(property::Running)] = g_param_spec_boolean("running", @@ -103,62 +162,104 @@ static void turns_turn_order_class_init(TurnsTurnOrderClass * klass) false, static_cast<GParamFlags>(G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY)); + properties[static_cast<std::size_t>(property::SortMode)] = + g_param_spec_enum("sort-mode", + "Sort Mode", + "The sort mode applied to the turn order", + TURNS_TYPE_TURN_ORDER_SORT_MODE, + TURNS_TURN_ORDER_SORT_MODE_DESCENDING, + static_cast<GParamFlags>(G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY)); + g_object_class_install_properties(object_class, properties.size(), properties.data()); } -static void turns_turn_order_init(TurnsTurnOrder * self) -{ - self->participants = nullptr; - self->running = false; -} +/* GListModel Implementation */ -static gpointer turns_turn_order_list_model_get_item(TurnsTurnOrder * self, guint position) +auto static turns_turn_order_list_model_get_item(TurnsTurnOrder * self, guint position) -> gpointer { g_return_val_if_fail(position < turns_turn_order_get_participant_count(self), nullptr); return g_object_ref(g_slist_nth_data(self->participants, position)); } -static guint turns_turn_order_list_model_get_n_items(TurnsTurnOrder * self) +auto static turns_turn_order_list_model_get_n_items(TurnsTurnOrder * self) -> guint { return turns_turn_order_get_participant_count(self); } -static GType turns_turn_order_list_model_get_item_type(TurnsTurnOrder * self) +auto static turns_turn_order_list_model_get_item_type(TurnsTurnOrder * self) -> GType { static_cast<void>(self); return TURNS_TYPE_PARTICIPANT; } -static void turns_turn_order_list_model_init(GListModelInterface * iface) +auto static turns_turn_order_list_model_init(GListModelInterface * iface) -> void { iface->get_item = std::bit_cast<decltype(iface->get_item)>(&turns_turn_order_list_model_get_item); iface->get_item_type = std::bit_cast<decltype(iface->get_item_type)>(&turns_turn_order_list_model_get_item_type); iface->get_n_items = std::bit_cast<decltype(iface->get_n_items)>(&turns_turn_order_list_model_get_n_items); } -TurnsTurnOrder * turns_turn_order_new() +/* Constructors */ + +auto turns_turn_order_new() -> TurnsTurnOrder * { return TURNS_TURN_ORDER(g_object_new(TURNS_TYPE_TURN_ORDER, nullptr)); } -void turns_turn_order_add(TurnsTurnOrder * self, TurnsParticipant * participant) +/* Functions */ + +auto turns_turn_order_add(TurnsTurnOrder * self, TurnsParticipant * participant) -> void { g_return_if_fail(participant != nullptr); - self->participants = g_slist_insert_sorted(self->participants, g_object_ref(participant), std::bit_cast<GCompareFunc>(&compare_participant)); g_signal_connect(participant, "notify::priority", std::bit_cast<GCallback>(&handle_participant_property_changed), self); + + auto sort_mode = turns_turn_order_get_sort_mode(self); + auto sort_data = std::bit_cast<void *>(static_cast<guintptr>(sort_mode)); + auto sort_function = std::bit_cast<GCompareDataFunc>(&compare_participant); + + self->participants = g_slist_insert_sorted_with_data(self->participants, g_object_ref(participant), sort_function, sort_data); + + auto position = g_slist_index(self->participants, participant); + + g_list_model_items_changed(G_LIST_MODEL(self), position, 0, 1); } -gsize turns_turn_order_get_participant_count(TurnsTurnOrder const * self) +/* Getters */ + +auto turns_turn_order_get_participant_count(TurnsTurnOrder const * self) -> gsize { g_return_val_if_fail(TURNS_IS_TURN_ORDER(const_cast<TurnsTurnOrder *>(self)), 0); return g_slist_length(self->participants); } -gboolean turns_turn_order_get_running(TurnsTurnOrder const * self) +auto turns_turn_order_get_running(TurnsTurnOrder const * self) -> gboolean { g_return_val_if_fail(TURNS_IS_TURN_ORDER(const_cast<TurnsTurnOrder *>(self)), false); return self->running; } +auto turns_turn_order_get_sort_mode(TurnsTurnOrder const * self) -> TurnsTurnOrderSortMode +{ + g_return_val_if_fail(TURNS_IS_TURN_ORDER(const_cast<TurnsTurnOrder *>(self)), TURNS_TURN_ORDER_SORT_MODE_ASCENDING); + return self->sort_mode; +} + +/* Setters */ + +auto turns_turn_order_set_sort_mode(TurnsTurnOrder * self, TurnsTurnOrderSortMode sort_mode) -> void +{ + g_return_if_fail(TURNS_IS_TURN_ORDER(self)); + + if (sort_mode == self->sort_mode) + { + return; + } + + self->sort_mode = sort_mode; + g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::SortMode)]); + + sort_participants(self); +} + G_END_DECLS
\ No newline at end of file diff --git a/lib/src/turns-turn-order.h b/lib/src/turns-turn-order.h index 4b1b61a..9d5c4b7 100644 --- a/lib/src/turns-turn-order.h +++ b/lib/src/turns-turn-order.h @@ -8,6 +8,12 @@ G_BEGIN_DECLS +typedef enum +{ + TURNS_TURN_ORDER_SORT_MODE_DESCENDING, + TURNS_TURN_ORDER_SORT_MODE_ASCENDING, +} TurnsTurnOrderSortMode; + #define TURNS_TYPE_TURN_ORDER turns_turn_order_get_type() G_DECLARE_FINAL_TYPE(TurnsTurnOrder, turns_turn_order, TURNS, TURN_ORDER, GObject) @@ -17,6 +23,9 @@ void turns_turn_order_add(TurnsTurnOrder * self, TurnsParticipant * participant) gsize turns_turn_order_get_participant_count(TurnsTurnOrder const * self) G_GNUC_WARN_UNUSED_RESULT; gboolean turns_turn_order_get_running(TurnsTurnOrder const * self) G_GNUC_WARN_UNUSED_RESULT; +TurnsTurnOrderSortMode turns_turn_order_get_sort_mode(TurnsTurnOrder const * self) G_GNUC_WARN_UNUSED_RESULT; + +void turns_turn_order_set_sort_mode(TurnsTurnOrder * self, TurnsTurnOrderSortMode sort_mode); G_END_DECLS diff --git a/lib/src/turnsmm/enums.cpp b/lib/src/turnsmm/enums.cpp index 91d6eb3..475d6f8 100644 --- a/lib/src/turnsmm/enums.cpp +++ b/lib/src/turnsmm/enums.cpp @@ -4,6 +4,7 @@ #include "turns-enums.h" // IWYU pragma: keep #include <glib-object.h> +#include <turns-turn-order.h> #include <type_traits> @@ -22,6 +23,9 @@ namespace Turns static_assert(matches<Disposition::Hostile, TURNS_DISPOSITION_HOSTILE>); static_assert(matches<Disposition::Secret, TURNS_DISPOSITION_SECRET>); + static_assert(matches<SortMode::Descending, TURNS_TURN_ORDER_SORT_MODE_DESCENDING>); + static_assert(matches<SortMode::Ascending, TURNS_TURN_ORDER_SORT_MODE_ASCENDING>); + } // namespace Turns namespace Glib @@ -33,6 +37,7 @@ namespace Glib } VALUE_SPECIALIZATION(Disposition, disposition) + VALUE_SPECIALIZATION(SortMode, turn_order_sort_mode) #undef VALUE_SPECIALIZATION } // namespace Glib
\ No newline at end of file diff --git a/lib/src/turnsmm/enums.hpp b/lib/src/turnsmm/enums.hpp index f99a6f1..b866b33 100644 --- a/lib/src/turnsmm/enums.hpp +++ b/lib/src/turnsmm/enums.hpp @@ -15,6 +15,12 @@ namespace Turns Secret, }; + enum struct SortMode + { + Descending, + Ascending, + }; + } // namespace Turns namespace Glib @@ -29,6 +35,7 @@ namespace Glib } VALUE_SPECIALIZATION(Disposition); + VALUE_SPECIALIZATION(SortMode); #undef VALUE_SPECIALIZATION diff --git a/lib/src/turnsmm/turn-order.cpp b/lib/src/turnsmm/turn-order.cpp index c89bd92..1f795d2 100644 --- a/lib/src/turnsmm/turn-order.cpp +++ b/lib/src/turnsmm/turn-order.cpp @@ -1,6 +1,7 @@ #include "turnsmm/turn-order.hpp" #include "turns-turn-order.h" +#include "turnsmm/enums.hpp" #include "turnsmm/participant.hpp" #include "turnsmm/private/turn-order_p.hpp" @@ -100,6 +101,26 @@ namespace Turns return {this, "running"}; } + auto TurnOrder::get_sort_mode() const noexcept -> SortMode + { + return static_cast<SortMode>(turns_turn_order_get_sort_mode(unwrap(this))); + } + + auto TurnOrder::set_sort_mode(SortMode value) noexcept -> void + { + turns_turn_order_set_sort_mode(unwrap(this), static_cast<TurnsTurnOrderSortMode>(value)); + } + + auto TurnOrder::property_sort_mode() noexcept -> Glib::PropertyProxy<SortMode> + { + return {this, "sort_mode"}; + } + + auto TurnOrder::property_sort_mode() const noexcept -> Glib::PropertyProxy_ReadOnly<SortMode> + { + return {this, "sort_mode"}; + } + TurnOrder::TurnOrder(BaseObjectType * gobj) : Glib::Object(G_OBJECT(gobj)) { diff --git a/lib/src/turnsmm/turn-order.hpp b/lib/src/turnsmm/turn-order.hpp index 9485275..c135ab2 100644 --- a/lib/src/turnsmm/turn-order.hpp +++ b/lib/src/turnsmm/turn-order.hpp @@ -2,6 +2,7 @@ #define TURNSMM_TURN_ORDER_HPP #include "turns-turn-order.h" +#include "turnsmm/enums.hpp" #include "turnsmm/participant.hpp" #include <glibmm/object.h> @@ -40,8 +41,13 @@ namespace Turns [[nodiscard]] auto get_participant_count() const noexcept -> std::size_t; [[nodiscard]] auto get_running() const noexcept -> bool; + [[nodiscard]] auto get_sort_mode() const noexcept -> SortMode; + + auto set_sort_mode(SortMode value) noexcept -> void; [[nodiscard]] auto property_running() const noexcept -> Glib::PropertyProxy_ReadOnly<bool>; + [[nodiscard]] auto property_sort_mode() noexcept -> Glib::PropertyProxy<SortMode>; + [[nodiscard]] auto property_sort_mode() const noexcept -> Glib::PropertyProxy_ReadOnly<SortMode>; protected: friend TurnOrder_Class; |
