Skip to content

Commit

Permalink
Add value gain/loss/change events.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Sep 19, 2020
1 parent 66ebb9e commit 4800982
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 1 deletion.
79 changes: 79 additions & 0 deletions src/alia/flow/events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,85 @@ on_init(context ctx, action<> on_init);
void
on_activate(context ctx, action<> on_activate);

template<class Value>
struct value_change_detection_data
{
captured_id id;
bool has_value;
Value value;
};

template<class Signal>
void
on_value_change(context ctx, Signal signal, action<> on_change)
{
value_change_detection_data<typename Signal::value_type>* data;
if (get_data(ctx, &data))
{
data->has_value = signal_has_value(signal);
if (data->has_value)
data->value = read_signal(signal);
}
refresh_signal_shadow(
data->id,
signal,
[&](auto const& new_value) {
if (!data->has_value || data->value != new_value)
{
perform_action(on_change);
mark_dirty_component(ctx);
data->has_value = true;
data->value = new_value;
}
},
[&] {
if (data->has_value)
{
perform_action(on_change);
mark_dirty_component(ctx);
data->has_value = false;
}
});
}

template<class Signal>
void
on_value_gain(context ctx, Signal signal, action<> on_gain)
{
bool* saved_state;
if (get_data(ctx, &saved_state))
*saved_state = true;
if (is_refresh_event(ctx))
{
bool current_state = signal_has_value(signal);
if (current_state && !*saved_state)
{
perform_action(on_gain);
mark_dirty_component(ctx);
}
*saved_state = current_state;
}
}

template<class Signal>
void
on_value_loss(context ctx, Signal signal, action<> on_loss)
{
bool* saved_state;
if (get_data(ctx, &saved_state))
*saved_state = false;
if (is_refresh_event(ctx))
{
bool current_state = signal_has_value(signal);
if (!current_state && *saved_state)
{
perform_action(on_loss);
mark_dirty_component(ctx);
}
*saved_state = current_state;
}
}

} // namespace alia

#endif
119 changes: 118 additions & 1 deletion unit_tests/flow/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <testing.hpp>

#include <alia/signals/basic.hpp>
#include <alia/signals/lambdas.hpp>
#include <alia/signals/operators.hpp>
#include <alia/signals/state.hpp>
#include <alia/system/internals.hpp>
Expand Down Expand Up @@ -101,7 +102,7 @@ TEST_CASE("event error propagation", "[flow][events]")
refresh_system(sys);
}

TEST_CASE("on_init/on_activate", "[signals][state]")
TEST_CASE("on_init/on_activate", "[flow][events]")
{
bool active = false;

Expand Down Expand Up @@ -158,3 +159,119 @@ TEST_CASE("on_init/on_activate", "[signals][state]")
REQUIRE(init_count == 1);
REQUIRE(activate_count == 3);
}

TEST_CASE("on_value events", "[flow][events]")
{
bool has_value = false;
int value = 0;

int gain_count = 0;
int gain_shadow = 0;

int loss_count = 0;
int loss_shadow = 0;

int change_count = 0;
int change_shadow = 0;

alia::system sys;
initialize_system(sys, [&](context ctx) {
on_refresh(ctx, [&](auto) {
gain_shadow = gain_count;
loss_shadow = loss_count;
change_shadow = change_count;
});

auto signal
= lambda_reader([&] { return has_value; }, [&] { return value; });

on_value_gain(ctx, signal, ++direct(gain_count));
on_value_loss(ctx, signal, ++direct(loss_count));
on_value_change(ctx, signal, ++direct(change_count));
});

refresh_system(sys);
REQUIRE(gain_count == 0);
REQUIRE(gain_shadow == 0);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 0);
REQUIRE(change_shadow == 0);

refresh_system(sys);
REQUIRE(gain_count == 0);
REQUIRE(gain_shadow == 0);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 0);
REQUIRE(change_shadow == 0);

has_value = true;
refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 1);
REQUIRE(change_shadow == 1);

refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 1);
REQUIRE(change_shadow == 1);

value = 2;
refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 2);
REQUIRE(change_shadow == 2);

refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 2);
REQUIRE(change_shadow == 2);

value = 1;
refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 0);
REQUIRE(loss_shadow == 0);
REQUIRE(change_count == 3);
REQUIRE(change_shadow == 3);

has_value = false;
refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 1);
REQUIRE(loss_shadow == 1);
REQUIRE(change_count == 4);
REQUIRE(change_shadow == 4);

refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 1);
REQUIRE(loss_shadow == 1);
REQUIRE(change_count == 4);
REQUIRE(change_shadow == 4);

value = 3;
refresh_system(sys);
REQUIRE(gain_count == 1);
REQUIRE(gain_shadow == 1);
REQUIRE(loss_count == 1);
REQUIRE(loss_shadow == 1);
REQUIRE(change_count == 4);
REQUIRE(change_shadow == 4);
}

0 comments on commit 4800982

Please sign in to comment.