summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2025-05-12 17:02:36 +0200
committerFelix Morgner <felix.morgner@gmail.com>2025-05-12 17:02:36 +0200
commit97c74a7c43bcc7e0551a967c6fa2720e9cb58efb (patch)
treec2ad9a76dbaf788bd8fdb41e5b18b75b7f7e3298 /lib
parent2618066ba0b9e7c490797821dca4d19b48a09256 (diff)
downloadturns-97c74a7c43bcc7e0551a967c6fa2720e9cb58efb.tar.xz
turns-97c74a7c43bcc7e0551a967c6fa2720e9cb58efb.zip
lib: add active and defeated properties to Turns.Participant
Diffstat (limited to 'lib')
-rw-r--r--lib/src/turns-participant.cpp75
-rw-r--r--lib/src/turns-participant.h32
-rw-r--r--lib/tests/turns-participant.cpp188
3 files changed, 287 insertions, 8 deletions
diff --git a/lib/src/turns-participant.cpp b/lib/src/turns-participant.cpp
index a94462e..49f29ff 100644
--- a/lib/src/turns-participant.cpp
+++ b/lib/src/turns-participant.cpp
@@ -17,6 +17,8 @@ struct _TurnsParticipant
{
GObject parent_instance;
+ gboolean active;
+ gboolean defeated;
TurnsDisposition disposition;
gchar * name;
gfloat priority;
@@ -30,7 +32,9 @@ namespace
{
enum struct property
{
- Disposition = 1,
+ Active = 1,
+ Defeated,
+ Disposition,
Name,
Priority,
N_PROPERTIES,
@@ -53,15 +57,16 @@ namespace
switch (static_cast<property>(id))
{
+ case property::Active:
+ return g_value_set_boolean(value, turns_participant_get_active(participant));
+ case property::Defeated:
+ return g_value_set_boolean(value, turns_participant_get_defeated(participant));
case property::Name:
- g_value_set_string(value, turns_participant_get_name(participant));
- return;
+ return g_value_set_string(value, turns_participant_get_name(participant));
case property::Priority:
- g_value_set_float(value, turns_participant_get_priority(participant));
- return;
+ return g_value_set_float(value, turns_participant_get_priority(participant));
case property::Disposition:
- g_value_set_enum(value, turns_participant_get_disposition(participant));
- return;
+ return g_value_set_enum(value, turns_participant_get_disposition(participant));
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification);
};
@@ -73,6 +78,10 @@ namespace
switch (static_cast<property>(id))
{
+ case property::Active:
+ return turns_participant_set_active(participant, g_value_get_boolean(value));
+ case property::Defeated:
+ return turns_participant_set_defeated(participant, g_value_get_boolean(value));
case property::Name:
return turns_participant_set_name(participant, g_value_get_string(value));
case property::Priority:
@@ -97,6 +106,20 @@ static void turns_participant_class_init(TurnsParticipantClass * klass)
object_class->set_property = set_property;
object_class->finalize = finalize;
+ properties[static_cast<std::size_t>(property::Active)] =
+ g_param_spec_boolean("active",
+ "Active",
+ "Whether or not the participant is currently active (taking their turn)",
+ false,
+ static_cast<GParamFlags>(G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+
+ properties[static_cast<std::size_t>(property::Defeated)] =
+ g_param_spec_boolean("defeated",
+ "Defeated",
+ "Whether or not the participant has been defeated",
+ false,
+ static_cast<GParamFlags>(G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+
properties[static_cast<std::size_t>(property::Name)] =
g_param_spec_string("name",
"Name",
@@ -142,6 +165,18 @@ TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priorit
g_object_new(TURNS_TYPE_PARTICIPANT, "name", name, "priority", priority, "disposition", static_cast<gint>(disposition), nullptr));
}
+gboolean turns_participant_get_active(TurnsParticipant const * self)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), false);
+ return self->active;
+}
+
+gboolean turns_participant_get_defeated(TurnsParticipant const * self)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), false);
+ return self->defeated;
+}
+
TurnsDisposition turns_participant_get_disposition(TurnsParticipant const * self)
{
g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), TurnsDisposition::TURNS_DISPOSITION_NEUTRAL);
@@ -160,6 +195,32 @@ gfloat turns_participant_get_priority(TurnsParticipant const * self)
return self->priority;
}
+void turns_participant_set_active(TurnsParticipant * self, gboolean value)
+{
+ g_return_if_fail(TURNS_IS_PARTICIPANT(self));
+
+ if (value == self->active)
+ {
+ return;
+ }
+
+ self->active = value;
+ g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::Active)]);
+}
+
+void turns_participant_set_defeated(TurnsParticipant * self, gboolean value)
+{
+ g_return_if_fail(TURNS_IS_PARTICIPANT(self));
+
+ if (value == self->defeated)
+ {
+ return;
+ }
+
+ self->defeated = value;
+ g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::Defeated)]);
+}
+
void turns_participant_set_disposition(TurnsParticipant * self, TurnsDisposition value)
{
g_return_if_fail(TURNS_IS_PARTICIPANT(self));
diff --git a/lib/src/turns-participant.h b/lib/src/turns-participant.h
index a2af8d6..a0e0d98 100644
--- a/lib/src/turns-participant.h
+++ b/lib/src/turns-participant.h
@@ -32,6 +32,22 @@ TurnsParticipant * turns_participant_new() G_GNUC_WARN_UNUSED_RESULT;
TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priority, TurnsDisposition disposition) G_GNUC_WARN_UNUSED_RESULT;
/**
+ * @brief Get the active state of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The active state of the instance.
+ */
+gboolean turns_participant_get_active(TurnsParticipant const * self);
+
+/**
+ * @brief Get the defeated state of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The defeated state of the instance.
+ */
+gboolean turns_participant_get_defeated(TurnsParticipant const * self);
+
+/**
* @brief Get the disposition of a participant.
*
* @param self A Participant instance. The value *must not* be NULL.
@@ -56,6 +72,22 @@ gchar const * turns_participant_get_name(TurnsParticipant const * self);
gfloat turns_participant_get_priority(TurnsParticipant const * self);
/**
+ * @brief Set the active state of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The new active state.
+ */
+void turns_participant_set_active(TurnsParticipant * self, gboolean value);
+
+/**
+ * @brief Set the defeated state of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @param value The new defeated state.
+ */
+void turns_participant_set_defeated(TurnsParticipant * self, gboolean value);
+
+/**
* @brief Set the disposition of a participant.
*
* @param self A Participant instance. The value *must not* be NULL.
diff --git a/lib/tests/turns-participant.cpp b/lib/tests/turns-participant.cpp
index 89e60cf..1211e4b 100644
--- a/lib/tests/turns-participant.cpp
+++ b/lib/tests/turns-participant.cpp
@@ -41,6 +41,16 @@ SCENARIO("Creating a participant", "[lib][object][lifetime]")
{
REQUIRE(turns_participant_get_disposition(instance) == TURNS_DISPOSITION_NEUTRAL);
}
+
+ THEN("it's active state is false")
+ {
+ REQUIRE_FALSE(turns_participant_get_active(instance));
+ }
+
+ THEN("it's defeated state is false")
+ {
+ REQUIRE_FALSE(turns_participant_get_defeated(instance));
+ }
}
GIVEN("A participant constructed using turns_participant_new_with(...)")
@@ -64,6 +74,16 @@ SCENARIO("Creating a participant", "[lib][object][lifetime]")
{
REQUIRE(turns_participant_get_disposition(instance) == disposition);
}
+
+ THEN("it's active state is false")
+ {
+ REQUIRE_FALSE(turns_participant_get_active(instance));
+ }
+
+ THEN("it's defeated state is false")
+ {
+ REQUIRE_FALSE(turns_participant_get_defeated(instance));
+ }
}
GIVEN("A participant is constructed using turns_participant_new_with(nullptr, ...)")
@@ -83,7 +103,7 @@ SCENARIO("Modifying a participant", "[lib][object][data]")
{
g_autoptr(TurnsParticipant) instance = turns_participant_new();
- WHEN("a new new is set")
+ WHEN("a new name is set")
{
auto new_value = "Test Participant";
@@ -128,6 +148,32 @@ SCENARIO("Modifying a participant", "[lib][object][data]")
}
}
+ WHEN("a new active state is set")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_active(instance) == new_value);
+ turns_participant_set_active(instance, new_value);
+
+ THEN("it's active state has the new value")
+ {
+ REQUIRE(turns_participant_get_active(instance) == new_value);
+ }
+ }
+
+ WHEN("a new defeated state is set")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_defeated(instance) == new_value);
+ turns_participant_set_defeated(instance, new_value);
+
+ THEN("it's defeated state has the new value")
+ {
+ REQUIRE(turns_participant_get_defeated(instance) == new_value);
+ }
+ }
+
AND_GIVEN("a signal handler has been subscribed to the name property")
{
auto was_notified = false;
@@ -301,6 +347,122 @@ SCENARIO("Modifying a participant", "[lib][object][data]")
}
}
}
+
+ AND_GIVEN("a signal handler has been subscribed to the active property")
+ {
+ auto was_notified = false;
+ g_signal_connect(instance, "notify::active", G_CALLBACK(&record_notification), &was_notified);
+
+ WHEN("a new active is set using set_active")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_active(instance) == new_value);
+ turns_participant_set_active(instance, new_value);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same active is set using set_active")
+ {
+ auto new_value = turns_participant_get_active(instance);
+
+ CHECK(turns_participant_get_active(instance) == new_value);
+ turns_participant_set_active(instance, new_value);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+
+ WHEN("a new active is set using g_object_set")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_active(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "active", new_value, nullptr);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same active is set using g_object_set")
+ {
+ auto new_value = turns_participant_get_active(instance);
+
+ CHECK(turns_participant_get_active(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "active", new_value, nullptr);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+ }
+
+ AND_GIVEN("a signal handler has been subscribed to the defeated property")
+ {
+ auto was_notified = false;
+ g_signal_connect(instance, "notify::defeated", G_CALLBACK(&record_notification), &was_notified);
+
+ WHEN("a new defeated is set using set_defeated")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_defeated(instance) == new_value);
+ turns_participant_set_defeated(instance, new_value);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same defeated is set using set_defeated")
+ {
+ auto new_value = turns_participant_get_defeated(instance);
+
+ CHECK(turns_participant_get_defeated(instance) == new_value);
+ turns_participant_set_defeated(instance, new_value);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+
+ WHEN("a new defeated is set using g_object_set")
+ {
+ auto new_value = true;
+
+ CHECK_FALSE(turns_participant_get_defeated(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "defeated", new_value, nullptr);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same defeated is set using g_object_set")
+ {
+ auto new_value = turns_participant_get_defeated(instance);
+
+ CHECK(turns_participant_get_defeated(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "defeated", new_value, nullptr);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+ }
}
}
@@ -349,5 +511,29 @@ SCENARIO("Reading a participant", "[lib][object][data]")
REQUIRE(getter_value == property_value);
}
}
+
+ WHEN("reading the active state via get_active and g_object_get")
+ {
+ auto getter_value = turns_participant_get_active(instance);
+ auto property_value = decltype(turns_participant_get_active(instance)){};
+ g_object_get(instance, "active", &property_value, nullptr);
+
+ THEN("they both compare equal")
+ {
+ REQUIRE(getter_value == property_value);
+ }
+ }
+
+ WHEN("reading the defeated state via get_defeated and g_object_get")
+ {
+ auto getter_value = turns_participant_get_defeated(instance);
+ auto property_value = decltype(turns_participant_get_defeated(instance)){};
+ g_object_get(instance, "defeated", &property_value, nullptr);
+
+ THEN("they both compare equal")
+ {
+ REQUIRE(getter_value == property_value);
+ }
+ }
}
} \ No newline at end of file