mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Add support for tracking the length of a model in C++
Similar to the parent commit, the model tracks changes to the rows and marks an internal property dirty. Since we have a base class this is a little less intrusive. cc #98
This commit is contained in:
parent
63bf1af093
commit
7d12fd7b4e
6 changed files with 49 additions and 2 deletions
|
@ -456,6 +456,11 @@ public:
|
||||||
/// Internal function called by the view to register itself
|
/// Internal function called by the view to register itself
|
||||||
void attach_peer(private_api::ModelPeer p) { peers.push_back(std::move(p)); }
|
void attach_peer(private_api::ModelPeer p) { peers.push_back(std::move(p)); }
|
||||||
|
|
||||||
|
/// \private
|
||||||
|
/// Internal function called from within bindings to register with the currently
|
||||||
|
/// evaluating dependency and get notified when this model's row count changes.
|
||||||
|
void track_row_count_changes() { model_dirty_property.get(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Notify the views that a specific row was changed
|
/// Notify the views that a specific row was changed
|
||||||
void row_changed(int row)
|
void row_changed(int row)
|
||||||
|
@ -465,11 +470,13 @@ protected:
|
||||||
/// Notify the views that rows were added
|
/// Notify the views that rows were added
|
||||||
void row_added(int index, int count)
|
void row_added(int index, int count)
|
||||||
{
|
{
|
||||||
|
model_dirty_property.set_dirty();
|
||||||
for_each_peers([=](auto peer) { peer->row_added(index, count); });
|
for_each_peers([=](auto peer) { peer->row_added(index, count); });
|
||||||
}
|
}
|
||||||
/// Notify the views that rows were removed
|
/// Notify the views that rows were removed
|
||||||
void row_removed(int index, int count)
|
void row_removed(int index, int count)
|
||||||
{
|
{
|
||||||
|
model_dirty_property.set_dirty();
|
||||||
for_each_peers([=](auto peer) { peer->row_removed(index, count); });
|
for_each_peers([=](auto peer) { peer->row_removed(index, count); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,6 +496,7 @@ private:
|
||||||
peers.end());
|
peers.end());
|
||||||
}
|
}
|
||||||
std::vector<private_api::ModelPeer> peers;
|
std::vector<private_api::ModelPeer> peers;
|
||||||
|
private_api::Property<bool> model_dirty_property;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace private_api {
|
namespace private_api {
|
||||||
|
|
|
@ -142,6 +142,7 @@ struct Property
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_dirty() const { return cbindgen_private::sixtyfps_property_is_dirty(&inner); }
|
bool is_dirty() const { return cbindgen_private::sixtyfps_property_is_dirty(&inner); }
|
||||||
|
void set_dirty() const { cbindgen_private::sixtyfps_property_set_dirty(&inner); }
|
||||||
|
|
||||||
static void link_two_way(const Property<T> *p1, const Property<T> *p2)
|
static void link_two_way(const Property<T> *p1, const Property<T> *p2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,6 +73,35 @@ TEST_CASE("Property Tracker")
|
||||||
REQUIRE(!tracker1.is_dirty());
|
REQUIRE(!tracker1.is_dirty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Model row changes")
|
||||||
|
{
|
||||||
|
using namespace sixtyfps::private_api;
|
||||||
|
|
||||||
|
auto model = std::make_shared<sixtyfps::VectorModel<int>>();
|
||||||
|
|
||||||
|
PropertyTracker tracker;
|
||||||
|
|
||||||
|
REQUIRE(tracker.evaluate([&]() {
|
||||||
|
model->track_row_count_changes();
|
||||||
|
return model->row_count();
|
||||||
|
}) == 0);
|
||||||
|
REQUIRE(!tracker.is_dirty());
|
||||||
|
model->push_back(1);
|
||||||
|
model->push_back(2);
|
||||||
|
REQUIRE(tracker.is_dirty());
|
||||||
|
REQUIRE(tracker.evaluate([&]() {
|
||||||
|
model->track_row_count_changes();
|
||||||
|
return model->row_count();
|
||||||
|
}) == 2);
|
||||||
|
REQUIRE(!tracker.is_dirty());
|
||||||
|
model->erase(0);
|
||||||
|
REQUIRE(tracker.is_dirty());
|
||||||
|
REQUIRE(tracker.evaluate([&]() {
|
||||||
|
model->track_row_count_changes();
|
||||||
|
return model->row_count();
|
||||||
|
}) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Image")
|
TEST_CASE("Image")
|
||||||
{
|
{
|
||||||
using namespace sixtyfps;
|
using namespace sixtyfps;
|
||||||
|
|
|
@ -1628,7 +1628,7 @@ fn compile_expression(
|
||||||
"[](const sixtyfps::Image &img) { return img.size(); }".into()
|
"[](const sixtyfps::Image &img) { return img.size(); }".into()
|
||||||
}
|
}
|
||||||
BuiltinFunction::ArrayLength => {
|
BuiltinFunction::ArrayLength => {
|
||||||
"[](const auto &model) { return (*model).row_count(); }".into()
|
"[](const auto &model) { (*model).track_row_count_changes(); return (*model).row_count(); }".into()
|
||||||
}
|
}
|
||||||
BuiltinFunction::Rgb => {
|
BuiltinFunction::Rgb => {
|
||||||
"[](int r, int g, int b, float a) {{ return sixtyfps::Color::from_argb_uint8(std::clamp(a * 255., 0., 255.), std::clamp(r, 0, 255), std::clamp(g, 0, 255), std::clamp(b, 0, 255)); }}".into()
|
"[](int r, int g, int b, float a) {{ return sixtyfps::Color::from_argb_uint8(std::clamp(a * 255., 0., 255.), std::clamp(r, 0, 255), std::clamp(g, 0, 255), std::clamp(b, 0, 255)); }}".into()
|
||||||
|
|
|
@ -1815,6 +1815,12 @@ pub(crate) mod ffi {
|
||||||
handle.0.access(|binding| binding.map_or(false, |b| b.dirty.get()))
|
handle.0.access(|binding| binding.map_or(false, |b| b.dirty.get()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marks the property as dirty and notifies dependencies.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sixtyfps_property_set_dirty(handle: &PropertyHandleOpaque) {
|
||||||
|
handle.0.mark_dirty()
|
||||||
|
}
|
||||||
|
|
||||||
/// Destroy handle
|
/// Destroy handle
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sixtyfps_property_drop(handle: *mut PropertyHandleOpaque) {
|
pub unsafe extern "C" fn sixtyfps_property_drop(handle: *mut PropertyHandleOpaque) {
|
||||||
|
|
|
@ -20,8 +20,11 @@ const TestCase &instance = *handle;
|
||||||
|
|
||||||
assert_eq(instance.get_num_ints(), 5);
|
assert_eq(instance.get_num_ints(), 5);
|
||||||
|
|
||||||
instance.set_ints(std::make_shared<sixtyfps::VectorModel<int>>(std::vector<int>{1, 2, 3, 4, 5, 6, 7}));
|
auto model = std::make_shared<sixtyfps::VectorModel<int>>(std::vector<int>{1, 2, 3, 4, 5, 6, 7});
|
||||||
|
instance.set_ints(model);
|
||||||
assert_eq(instance.get_num_ints(), 7);
|
assert_eq(instance.get_num_ints(), 7);
|
||||||
|
model->push_back(8);
|
||||||
|
assert_eq(instance.get_num_ints(), 8);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue