Fix removing from model in C++

This commit is contained in:
Olivier Goffart 2020-09-30 18:17:15 +02:00
parent 5fbe79006c
commit f01977ca06
3 changed files with 44 additions and 9 deletions

View file

@ -362,13 +362,13 @@ struct IntModel : Model<int>
/// A Model backed by a SharedArray /// A Model backed by a SharedArray
template<typename ModelData> template<typename ModelData>
class SharedArrayModel : public Model<ModelData> class VectorModel : public Model<ModelData>
{ {
SharedArray<ModelData> data; std::vector<ModelData> data;
public: public:
SharedArrayModel() = default; VectorModel() = default;
SharedArrayModel(SharedArray<ModelData> array) : data(std::move(array)) { } VectorModel(std::vector<ModelData> array) : data(std::move(array)) { }
int row_count() const override { return data.size(); } int row_count() const override { return data.size(); }
ModelData row_data(int i) const override { return data[i]; } ModelData row_data(int i) const override { return data[i]; }
void set_row_data(int i, const ModelData &value) override void set_row_data(int i, const ModelData &value) override
@ -377,12 +377,19 @@ public:
this->row_changed(i); this->row_changed(i);
} }
// Append a new row with the given value /// Append a new row with the given value
void push_back(const ModelData &value) void push_back(const ModelData &value)
{ {
data.push_back(value); data.push_back(value);
this->row_added(data.size() - 1, 1); this->row_added(data.size() - 1, 1);
} }
/// Remove the row at the given index from the model
void erase(int index) {
data.erase(data.begin() + index);
this->row_removed(index, 1);
}
}; };
template<typename C, typename ModelData> template<typename C, typename ModelData>
@ -409,7 +416,12 @@ class Repeater
data[index].state = State::Dirty; data[index].state = State::Dirty;
} }
void row_removed(int index, int count) override { void row_removed(int index, int count) override {
is_dirty = true;
data.erase(data.begin() + index, data.begin() + index + count); data.erase(data.begin() + index, data.begin() + index + count);
for (std::size_t i = index; i < data.size(); ++i) {
// all the indexes are dirty
data[i].state = State::Dirty;
}
} }
}; };

View file

@ -28,6 +28,7 @@ TestCase := Rectangle {
property <int> clicked_score; property <int> clicked_score;
property <string> clicked_name; property <string> clicked_name;
property <int> clicked_internal_state; property <int> clicked_internal_state;
property <int> clicked_index;
for person[i] in model: TouchArea { for person[i] in model: TouchArea {
x: i*10px; x: i*10px;
@ -42,6 +43,7 @@ TestCase := Rectangle {
clicked_internal_state = internal_state; clicked_internal_state = internal_state;
clicked_score = score; clicked_score = score;
clicked_name = text; clicked_name = text;
clicked_index = i;
} }
} }
} }
@ -73,6 +75,7 @@ instance.set_model(Some(another_model.clone()));
sixtyfps::testing::send_mouse_click(instance, 25., 5.); sixtyfps::testing::send_mouse_click(instance, 25., 5.);
assert_eq!(instance.get_clicked_score(), 333000); assert_eq!(instance.get_clicked_score(), 333000);
assert_eq!(instance.get_clicked_internal_state(), 1); assert_eq!(instance.get_clicked_internal_state(), 1);
assert_eq!(instance.get_clicked_index(), 2);
sixtyfps::testing::send_mouse_click(instance, 15., 5.); sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq!(instance.get_clicked_score(), 222000); assert_eq!(instance.get_clicked_score(), 222000);
@ -91,6 +94,15 @@ sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq!(instance.get_clicked_score(), 555000); assert_eq!(instance.get_clicked_score(), 555000);
assert_eq!(instance.get_clicked_name(), sixtyfps::SharedString::from("idyllic")); assert_eq!(instance.get_clicked_name(), sixtyfps::SharedString::from("idyllic"));
assert_eq!(instance.get_clicked_internal_state(), 2); assert_eq!(instance.get_clicked_internal_state(), 2);
assert_eq!(instance.get_clicked_index(), 1);
another_model.remove(1);
sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq!(instance.get_clicked_score(), 333000);
assert_eq!(instance.get_clicked_name(), sixtyfps::SharedString::from("world"));
assert_eq!(instance.get_clicked_internal_state(), 2);
assert_eq!(instance.get_clicked_index(), 1);
``` ```
```cpp ```cpp
@ -106,16 +118,17 @@ assert_eq(instance.get_clicked_score(), 789000);
assert_eq(instance.get_clicked_internal_state(), 1); assert_eq(instance.get_clicked_internal_state(), 1);
using ModelData = std::tuple<sixtyfps::SharedString, sixtyfps::SharedString, float>; using ModelData = std::tuple<sixtyfps::SharedString, sixtyfps::SharedString, float>;
sixtyfps::SharedArray<ModelData> array; std::vector<ModelData> array;
array.push_back(ModelData{"a1", "hello", 111.}); array.push_back(ModelData{"a1", "hello", 111.});
array.push_back(ModelData{"a2", "cruel", 222.}); array.push_back(ModelData{"a2", "cruel", 222.});
array.push_back(ModelData{"a3", "world", 333.}); array.push_back(ModelData{"a3", "world", 333.});
auto another_model = std::make_shared<sixtyfps::SharedArrayModel<ModelData>>(array); auto another_model = std::make_shared<sixtyfps::VectorModel<ModelData>>(std::move(array));
instance.set_model(another_model); instance.set_model(another_model);
sixtyfps::testing::send_mouse_click(instance, 25., 5.); sixtyfps::testing::send_mouse_click(instance, 25., 5.);
assert_eq(instance.get_clicked_score(), 333000); assert_eq(instance.get_clicked_score(), 333000);
assert_eq(instance.get_clicked_internal_state(), 1); assert_eq(instance.get_clicked_internal_state(), 1);
assert_eq(instance.get_clicked_index(), 2);
sixtyfps::testing::send_mouse_click(instance, 15., 5.); sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq(instance.get_clicked_score(), 222000); assert_eq(instance.get_clicked_score(), 222000);
@ -133,6 +146,16 @@ sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq(instance.get_clicked_score(), 555000); assert_eq(instance.get_clicked_score(), 555000);
assert_eq(instance.get_clicked_name(), "idyllic"); assert_eq(instance.get_clicked_name(), "idyllic");
assert_eq(instance.get_clicked_internal_state(), 2); assert_eq(instance.get_clicked_internal_state(), 2);
assert_eq(instance.get_clicked_index(), 1);
another_model->erase(1);
sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq(instance.get_clicked_score(), 333000);
assert_eq(instance.get_clicked_name(), "world");
assert_eq(instance.get_clicked_internal_state(), 2);
assert_eq(instance.get_clicked_index(), 1);
``` ```
*/ */

View file

@ -75,11 +75,11 @@ sixtyfps::testing::send_mouse_click(instance, 15., 5.);
assert_eq(instance.get_clicked_score(), 791); assert_eq(instance.get_clicked_score(), 791);
using ModelData = std::tuple<sixtyfps::SharedString, sixtyfps::SharedString, float>; using ModelData = std::tuple<sixtyfps::SharedString, sixtyfps::SharedString, float>;
sixtyfps::SharedArray<ModelData> array; std::vector<ModelData> array;
array.push_back(ModelData{"a1", "hello", 111.}); array.push_back(ModelData{"a1", "hello", 111.});
array.push_back(ModelData{"a2", "cruel", 222.}); array.push_back(ModelData{"a2", "cruel", 222.});
array.push_back(ModelData{"a3", "world", 333.}); array.push_back(ModelData{"a3", "world", 333.});
auto another_model = std::make_shared<sixtyfps::SharedArrayModel<ModelData>>(array); auto another_model = std::make_shared<sixtyfps::VectorModel<ModelData>>(std::move(array));
instance.set_model(another_model); instance.set_model(another_model);
sixtyfps::testing::send_mouse_click(instance, 25., 5.); sixtyfps::testing::send_mouse_click(instance, 25., 5.);