summaryrefslogtreecommitdiff
path: root/lib/src
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2025-05-19 13:42:39 +0200
committerFelix Morgner <felix.morgner@gmail.com>2025-05-19 13:42:39 +0200
commit0a5f3b25214c11556f62ce04601c06812a3464d8 (patch)
treed35ed88fc142927f6d34af7e0ddcc4bafb25145a /lib/src
parentd0b647c3156b07c70e9831aa86ef76ee40413d0c (diff)
downloadturns-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.cpp191
-rw-r--r--lib/src/turns-turn-order.h9
-rw-r--r--lib/src/turnsmm/enums.cpp5
-rw-r--r--lib/src/turnsmm/enums.hpp7
-rw-r--r--lib/src/turnsmm/turn-order.cpp21
-rw-r--r--lib/src/turnsmm/turn-order.hpp6
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;